ILE RPG: “Specifications and operations – new and obsolete codes”

After a first analysis about the ILE RPG components and the binding logic, see the previous post at the link , I want to have a look deeply inside the use of the code, trying to discover and explain the main differences between old RPG and ILE RPG.



I discussed previously about the advantages of ILE RPG in term of readability: extended rows and indented code are only a few of the advantages available to improve the code readability.

In general, the best way to use ILE RPG is the complete free-form style: this avoid mixture of code and keep the code more readable. In addition to this it is important to code in a modern style avoiding bad and old habits and practices: in the modern language a lot of obsolete codes has been removed to use new modern codes. For example the following codes has been removed and are no longer available:


For a good programming style you should also avoid numeric indicator (*IN01-*IN99) and special indicator (*INU1-*INU8), because they are not self-explanatory and you should use Boolean variables to show better the meaning of the conditions.

If the program defines a display/print file with resulting indicators, you could define an Indicator Data Structure to remap them inside the program with meaningful names.



One of the stronger changes in free-form language of ILE RPG, from the 7.2 version, was to provide alternatives for all data declarations and for many file declarations.

This release removes too the need for the /Free and /End-Free directives. The compiler assumes that the source line is in free-form if columns 6 and 7 are left blanks.

F and D spec entries become declarations. A declaration starts by the string DCL and is followed by the type of declaration. All the new declarations follow the same basic format, in the following order:

  • DCL-xx
  • the name of the item (file, DS, field ….)
  • keywords to replace the column-sensitive entries
  • any keywords that are in the D and F spec option columns
  • a semi-colon (; ) that terminates the definition

Another important change is the introduction of a number of defaults: for example all files are assumed external unless otherwise specified; all numeric fields are assumed to have zero decimal unless otherwise specified and so on.


I realized the following table that resumes the different kind of specifications used in the old and new languages. It could be not perfect or exhaustive but it will let you have an idea of the language evolution:


OLD Version of positional RPG H SPEC





Arrays, tables


Records, fields, DS, Constant



ILE RPG positional H SPEC




                    D SPEC

         Fields, Constants, DS



Free form ILE RPG ctl-opt




                dcl-s   dcl-ds

Fields, Constants, DS

Free spec



In the same way of file declaration you could define prototypes, interfaces and procedures by using the declarations:

DCL-PR (prototype)

DCL-PL (Interface)

DCL-PROC (procedure)

And everyone of these have the corresponding END-XX tag.


Now, with more details, we could analyze a bit the new kind of specifications:

A) H Specifications become ctl-opt but it has similar meaning and use, for example:

H option(*nodebugio)

ctl-opt option(*nodebugio);


ctl-opt nomain;


B) F specifications become ctl-f

You don’t need to tell the compiler that files are externally described even if RPG let you specify *EXT as a parameter to the device type keyword. With the new default you can omit the device type and the compiler assumes an input DISK file. In the same way you don’t need to specify that a PRINTER file is an output file. The default file usage is related to the device type and you could specify it only when you want to change the default value.

So the following declarations are equivalent:

Dcl-F File_name;

Dcl-F File_name Disk;

Dcl-F File_name Disk(*Ext) Usage(*Input);


The following tables show you the default types and their usage:


 C) D Specifications become dcl-s or dcl-ds

D specifications are replaced by the following, showed in this table:

The important thing is that now we use keyword instead of code. For example alphanumeric fields are now declared by the expression:


and packed by:

PACKED(digits : decimals)


For a complete list of fixed form and free form data definition correspondences, see the following tables:





In the following tables that I got from the “Rational Development Studio for i

ILE RPG Language Reference” we have the list of the OPERATION CODES both in Free-Form Syntax (based on version 7.1 of the operating system) and the Traditional Syntax. Tables are enriched by Exenders to add meaning.



The next table lists all operation codes about TRADITIONAL SYNTAX:















RPGILE Components.

After a little overview on the history of RPG language in the previous post   I would introduce basic components and concepts about RPG ILE language.

An ILE PROGRAM in general consists in one or more MODULE and every module consist in one or more PROCEDURES called subprocedures. If a subprocedure can be used in more then one place it belongs in a SERVICE PROGRAM.

Now we could have a deeper analysis on these components trying to understand their meaning and their use.



When we talk about subprocedures we could refer to different kind of objects:

  • ILE modules
  • Main procedures
  • Built-in functions
  • Subroutine

I would examine a little bit the different meaning of these components:

ILE Modules

An ILE MODULE is a single unit od code that could be grouped in one of the following:

  • with a main procedure and no subprocedures
  • with a main procedure and one or more subprocedures
  • with no main procedure but with one or more subprocedures

Main procedures

The main procedures are procedures that could be called both by a dynamic CALL or by a bound CALL. Subprocedures must always be called by a bound call: this is because subprocedures can only be used in programs that are created by Create Program (CRTPGM) or by Create Bound RPG Program (CRTBNDRPG) commands.

Built-in function

These are subprocedures that are defined to return a value as functions or user-defined functions.


Subroutines are different from subprocedures even if they have the same meaning because they are used to wrap re-usable code in a bigger part of code. Subprocedures offer more advantages respect to the subroutine. For example they can define local variables, they can accept parameters, they can provide parameters checking, they can be used as a function.

 Service program

Service programs are collections of modules, especially if the modules contain subprocedures to share. The main advantage to use service program is to avoid to bind the modules that contain the procedures, by copying the compiled code into every program. Service programs are object of kind *SRVPGM and cannot directly called but must be called by ILE programs or other procedures.



ILE programs and service programs are created by using the process called “binding”. This process copies the compiled code from module objects to create program and service program. The binding process can also bind a program to a service program by reference, to use it at run time.

An ILE program can be created by using the CRTPGM command from one or more module objects. CRTPGM can also bind the program to ONE OR MORE SERVICE PROGRAM.

The “Module parameter” of CRTPGM lists all the modules that are copied into the bound program.

The “Service program parameter” of CRTPGM lists all the service programs that are to be referenced by the program at run time.

Service program object are created by using Create Service Program (CRTSRVPGM) in the same way of creating programs. RPG ILE programs can also be created by using the Create Bound RPG Program (CRTBNDRPG) command: this command performs both compilation and binding in a single step. If the program needs to copy any modules or to reference any service programs, then a Binding Directory is required.


Binding directories

A binding directory (object type *BNDDIR) is a list of modules and service programs that could be binded into a program that needs them.

The binding directories are created by two CL commands:

  • Create Binding Directory (CRTBNDDIR)
  • Add Binding Directory (ADDBNDDIRE) or Work with Binding Directory Entries (WRKBNDDIRE)

The CRTBNDDIR creates an object of *BNDDIR type. The ADDBNDDIRE command adds an entry to the directory list.


Activation groups

The activation group is a part of the job structure and let to run programs in isolated environments. It is created when an ILE program or a service program is started or activated. It is recommended to run ILE program in an defined activation group, used when the program is created, instead of leave the default activation group: this will let you to scope the commitment control and the file overrides.

There are three types of activation groups: default, named and new.

About the default activation group there are two default activation group:

  • activation group 1, reserved for many system programs
  • activation group 2, for the RPG IV programs that are created with DFTACTGRP(*YES) of the CRTBNDRPGM

The other types of activation groups are created by CRTPGM and CRTSRVPGM at creation time of the program.

An activation group is created when the program starts and it could include these entities:

  • static and automatic variables

static variables are those that are defined in a main procedure or they come externally from DDS and SQL specifications; or are defined as STATIC in a subprocedure.

Automatic variables are local variables defined in subprocedures.

  • open data paths

these are open files to program, for example data buffers and pointers to records.

  • dynamically allocated storage

these are temporary objects created by the %alloc built-in functions

  • error handling routine

these are modules that handle error messages

The CRTPGM and CRTSRVPGM and the CRTBNDRPG let to define the activation group with these values:

  1. NEW: a new activation group is created every time that the program is called. This could be a cause of PERFORMANCE PROBLEMS because a new set of static variables and open data paths are created each time the program is called.
  2. *ENTMOD: in this case the program entry procedure module is examined to estabilish which kind of activation group must be used (please consult the help to discover all the cases)
  3. NAME a named activation group is created if it doesn’t exists. This is the best situation because it enables separation of applications in efficient way. It should be used on the main program and all the other should use *CALLER or the same name.
  4. *CALLER: the ACTGRP(*CALLER) parameters indicates that the service program runs in the same activation group as its caller.


While we are near the 30th year of IBM i, in next June, I want to continue in my education pattern trough the modernization steps. I analyzed in the previous posts the importance of an extended SQL database and the use of modern tools developed with an IDE environment (I suggest you to have a look at the previous posts by the link  It is now the moment to start the analysis of the “MODERN LANGUAGES” phase; to do it I prefer to have a little tour back into the RPG history, in the past years..



RPG is an high-level programming language (HLL) for business applications. It has a long history because it was developed by IBM in 1959 as a Report Program Generator a kind of tool to replicate “punched card” processing on the old IBM 1401. It was updated to RPG II for IBM System/3 in the 1960s and evolved into an HLL language as COBOL and PL/I.

In the far past of RPG, its major strength was the “program cycle”: every RPG program processes an implied loop that can apply the program to every record of a file. Each record (individual punched card) was compared to each line inside the program, which could be executed or not based on the value of an indicator inside the set of 01-99. Since the introduction of the System 38 in 1979 most RPG programmers stopped the use of the cycle to a better controlling program flow with standard constructs.

RPG typically used then File Specifications (lines to use files for read/update), followed by Data Definition Specification that contains Data Structures and arrays; then Calculation Specifications to write executable instructions.



RPGII, introduced with System/3, was later used on System/32, System/34 and System/36 with a better version of the language. It was also available for larger systems as System/370 mainframe.

RPG III born on the System/38 and its successor AS/400. RPG mainly changed from the original language providing modern constructs like IF-ENDIF blocks, DO loops and subroutines.

RPG/400 started as RPG III running on AS/400. Even if IBM renamed RPG compiler as “RPG/400”, the language was identic to the RPG III. Nothing of new into the language until IBM delivered new operation codes, such as SCAN, CAT and XLATE after a lot of years of AS/400 availability.

RPG IV (RPGLE or ILE RPG) born on 1994 by the V3R2 release of OS/400 Operating system. RPG IV delivered a lot of expressions within its Extended Factor 2 Calculation Specification and after by its free-format Calculation Specifications. RPG IV is the ONLY VERSION OF RPG SUPPORTED on the long set of AS400 successors (iSeries, System i, etc.)

It was in 2001 with the OS/400 V5R1 that RPG IV offered freedom for calculations by the use of free-format text entry as alternative to the old column-dependent source format. Until November 2013 the free format was available only on calculation specifications. With the IBM i V7R1 TR7 and more the “/free” and “/end-free” calculations are no longer necessary, so the language definitely abandoned the “punched cards” ties.

Today RPG IV is a robust language; even if it could be edited by old editors as SEU, the best way to use it is by IDE tools based on Eclipse: RDI (Rational Developer for I, as IBM example) is one example of these. IBM is extending RPG capabilities continuously, so now it has more built-in functions, it could link Java objects and i5/OS APIs. It could integrates tools as CGIDEV2 for CGI programs, RPG Toolbox, cozTools and othe commercial tools or solution for modernization use.

In 2006 OS/400 was renamed i5/OS, under the new brand “IBM System i5”. After the 5 was dropped and the new brand becomes “System I”. In March 2008 i5/OS changed in IBM i as component of the Power Systems new server models. The latest release is the IBM i 7.3 and it supports the RPG IV language.



The RPGLE is surely a language closer to modern object oriented language instead of the old column based RPG. It runs in ILE (Integrated Language Environment) instead of OPM (Original Program Model) and it allow the use of service programs an modules that could let you have modularity with static binding avoiding external calls.

It supports the use of other languages such as ILE/C and BIFs (Built In Functions).

For more usability it let you use longer file/fields name and prefixes and free format code, as every modern language now in use.

These are only the main reasons that must suggest you to move to this modern version of old RPG, in order to let you realize application opened to the web and other environment.

Redbook updates: “Enhancing the IBM Power Systems Platform with IBM Watson Services”


I updated the RedBooks Section with this RedBook about IBM Watson services……


This IBM® Redbooks® publication provides an introduction to the IBM POWER® processor architecture. It describes the IBM POWER processor and IBM Power Systems™ servers, highlighting the advantages and benefits of IBM Power Systems servers, IBM AIX®, IBM i, and Linux on Power.

This publication showcases typical business scenarios that are powered by Power Systems servers. It provides an introduction to the artificial intelligence (AI) capabilities that IBM Watson® services enable, and how these AI capabilities can be augmented in existing applications by using an agile approach to embed intelligence into every operational process. For each use case, the business benefits of adding Watson services are detailed.

This publication gives an overview about each Watson service, and how each one is commonly used in real business scenarios. It gives an introduction to the Watson API explorer, which you can use to try the application programming interfaces (APIs) and their capabilities. The Watson services are positioned against the machine learning capabilities of IBM PowerAI.

In this publication, you have a guide about how to set up a development environment on Power Systems servers, a sample code implementation of one of the business cases, and a description of preferred practices to move any application that you develop into production.

This publication is intended for technical professionals who are interested in learning about or implementing IBM Watson services on AIX, IBM i, and Linux.

RDI: “Debugging”

After the introduction we had with the previous posts and the compiling details, see the links:




I would approach a bit one of the most powerful features of RDI, the debugging. I am sure I couldn’t be exhaustive because the argument is complex and articulated, but I will cover the most important aspects able to let you work on it in your daily activities.

The main way to execute a debug on RDI is to work by Service Entry Points. You have the possibility to choose an LE program to start, it doesn’t matter if it is batch, or a web service or a service program and you could immediately activate all the debug options that RDI include, we will see it later.

But how to debug when SEP doesn’t works? For example for an old RPG program or when the program is running, like a never ending program. In these cases you should choose one of the existing configurations that RDI offers and work by it. In this post for a short exposition I would show you about Interactive debug and debug by Processes adding to SEP.

First have a look at this screen, where you could see how to launch the Debug Configuration Panel:


You will see all the available kinds of debug that you can activate adding to SEP:



DEBUGGING ON RDI BY SEP (Service Entry Point):

When you want to debug a LE program, the first think is to set the entry point by right click on the object list:

or by using the menu on the SEP Tabbed:

This panel will be opened and you must indicate the program (or the service program), the library and the User ID.

The debug will be activate when that user will launch the program.


If you confirm you should see a Confirm window and your program/SEP listed in the tabbed:


Every SEP could be managed by activation/deactivation, update and other options into the menu. For example, in case you recompile the program you should only UPDATE the SEP:


At this point you should start your program and then the debug will be activated.

You should do this by launching interactive debugging or by calling the program directly.  Let us see the first case. Right click on the program and execute the interactive debug:

A warning window asks you to activate RSE Server by a CL program:

Sometime this command doesn’t works, maybe because the firewall blocks it:

So we could call the program directly:

Immediately RDI answers asking to pass on Debug View:

And we are in the debug view with our program opened and ready for debug:

There are a lot of different options to use the debug. For example to navigate inside program jumping from a brekpoint to another you could use F5/F6/F7 to move on, to pass on and to move back to a breakpoint. F8 will let you continue the process:

On the right side you could see the variables. You are able to change their value and you could select an expression in your code and test it:

You could add or remove breakpoint by double-click on the row:

Or you could change the breakpoint by adding conditions:

Another possibility you have is to the code execution step by step with the following options related to the velocity of the execution:



Coming back to interactive debug I want to show you what happens when RSE starts normally. I launch it by main menu:

A window asks me to start RSE server:

and in the 5250 session the program is automatically executed:

RDI asks you to switch in debug view:

And as the previous case the debug view is opened with the program to debug:



Another easy way you could use for debug, especially when SEP doesn’t works, is debugging by processes. You could easily select your process inside the active processes of the user:  

Then you could execute the debug as an IBM i job:

As the usual RDI will ask you to switch to debug view and then, after you will call the program in the same process you indicated, the debug will be activated and ready to be used.