Sat, Apr
5 New Articles

Wanna Play Center Field?

  • Smaller Small Medium Big Bigger
  • Default Helvetica Segoe Georgia Times

Many of the classes we attended at COMMON’s fall 1999 conference in San Antonio were about taking advantage of ILE. One such class was Jon Paris’ session in which he discussed new features for V4R4 of the OS/400. Jon talked about RPG's new EVALR operation code, which is basically an EVAL statement that moves the result to the right, padding the result field with leading blanks. Someone raised the question, “When are we going to get an EVALC to center the results?” Although Jon was not able to predict when IBM might announce such a feature, the question made us wonder whether we could to do such a thing in a sensible manner.

Obviously, we couldn’t write an EVALC op code. But what we could do was write an ILE procedure that we could use to center text within a field. After some trials and tribulations, we came up with a nifty little procedure to center text. Think of this article as a forum for sharing some of the information we learned about dealing with ILE procedures. It is our pleasure, therefore, to chronicle the development process of the ILE procedure named CenterFld.

Put Me In, Coach!

Although our package was converted to ILE RPG years ago, we were not taking advantage of the many ILE features. Now it was time to take that next step. We had attended enough classes and read enough books. We felt that we were ready and armed with enough information to be dangerous. We wanted to create an ILE procedure that would accept a text field of any size and return the text centered within that field.

The first step in creating an ILE procedure is to define the procedure interface. The definition phase basically consists of defining the parameters for the procedure as well as defining the parameter returned to the calling program (if any). For the purposes of the CenterFld procedure, we wanted a varying length input and return field. We had seen the Varying keyword on a number of examples in manuals and in COMMON session handouts, so we thought it would be a “piece of cake.” We tried this:

D CenterFld PI 32766 varying
D FieldToCtr 32766 varying

You would think that with as many years as we have been programming, we should know better than to think that any job is a piece of cake. Such thoughts should immediately evoke images of that crazy robot in Lost in Space wildly flailing its arms about, screaming, “Danger! Danger, Will Robinson!” Unfortunately, we are living proof that age does not always bring wisdom.

As it turns out, the Varying keyword actually defines a special type of variable, that is, a variable-length variable. What this means is that the calling program of the procedure would have to define a special varying-length field in the calling program to use the procedure. This was not what we wanted. In fact, this keyword wasn’t what we wanted at all! We wanted to define a parameter that could be any size field, not a field that could be any length. We found what we were looking for with the OPTIONS(*VARSIZE) keyword. This keyword allowed us to define a parameter that can vary in size. In other words, it can pass a 10-byte field one time and a 100-byte field the next, and the procedure will still work. Take a gander at the code in Figure 1 to see how the parameter should be defined.

We had solved our first problem after only a day of trial and error. What did we learn? We learned that reading the manual before you start using a new keyword can save a lot of time.

Once we had the procedure interface defined correctly, we needed to “prototype” it. All this means is that you need to define the parameters with a Prototype (PR) statement vs. a Procedure Interface (PI) statement. Figure 2 shows the prototype definition for the CenterFld procedure. Every program that calls the procedure module will require the prototype definitions. The procedure module itself will use the procedure interface definition. Since the same prototype will be used by every calling program, it’s best to put it into a source member and use /COPY to bring it into the calling program. We created a source file called prsource in library ileexample to store our prototype definitions.

Batter Up!

Now that we could define a variable-length parameter, we encountered our next challenge. We needed to know the length of the field that was being passed to us to be able to center it. Once again, we were back digging through the manuals. It was there that we came upon the Retrieve Operational Descriptor API, CEEDOD. The CEEDOD API tells you program information about the parameters passed to the procedure.

We found a great example of this API in the ILE RPG for AS/400 Programmer’s Guide. For our purposes, we were able to key the sample code directly into our program. The procedure interface needs an Operational Descriptor (opdesc) keyword to tell the system to pass the information about the parameters to the called procedure. One of the parameters, INLEN, is the length of the parameter being passed. We were able to use the checkr op code to get the position of the last non-blank character in the field. With this information, the calculation to center the text within the parameter becomes reasonably straightforward.

At the Wall

One of the cool things about ILE is that you can put together a collection of tools that will always be available to your calling programs. The way to do this is by placing the tools in an object called a service program. Because the CenterFld function was going to be one of a number of tools we wanted to make available to our calling programs, it was logical for us to put the procedure into a service program.

As a general rule, service programs should consist of a few modules that perform similar functions. The reason for this is that all modules in the service program are brought into memory when the service program is first activated, even if the calling program does not use them. Logically, you would want to keep your service programs small to minimize lag time during program initiation if the service program gets too large.

We created our service program and named it TOOLS. The TOOLS service program contains the CenterFld module as well as a few others not shown in this article.

When we first attempted to create our service program, we encountered another problem. We took the defaults on the Export parameter on the Create Service Program (CRTSRVPGM) command, and it expected us to have a source member (with the same name as the service program we were creating) in a source file named QSRVSRC. We found that you can bypass this requirement by specifying EXPORT(*ALL), but there are some reasons why you should not do this. Those reasons are maintenance, maintenance, and maintenance!

If there is even the remotest possibility that you will someday add functions to a service program, your life will be made easier with the accompanying source member. When you make a change to the exports of a service program and you do not have the source member, you will need to find and recompile every program that references the service program. On the other hand, if you have the appropriate source member, you can create a new interface specification and all the existing programs will use the old interface. The existing programs that reference the service program will not need to be recompiled.

The following example displays the binder language source member for the TOOLS service program:


Binder language source members can be of any source member type. We chose to use SRVPGM type to designate what we were using the source member for. We didn’t want to use an existing source member type (like RPGLE), because you don’t compile these source members. They are used only when creating a service program. Once our source member was prepared, we created our service program with the following command:


Let’s take another look at the source in the TOOLS service program. The STRPGMEXP/ENDPGMEXP are paired, much like If/End statements in RPG. In between the start and the end, you need one EXPORT statement for each module in the service program that you wish to use outside of the service program itself.

Binder language has a unique way to manage the various service program levels that enables you to change a service program and not adversely affect all programs referencing it. This method uses the Program level (PGMLVL) parameter on the STRPGMEXP statement. The PGMLVL parameter accepts *CURRENT for the latest and greatest or *PRV for prior versions of the service program.

Here’s an example that shows you how to use the PGMLVL parameter to maintain different levels of a service program:


You can see how our source member should look after adding a new module (EXISTS) to the service program. Any new programs that are compiled using this service

program would use the *CURRENT definition and thus be able to access all modules in that STRPGMEXP/ENDPGMEXP paired grouping. Conversely, programs that were compiled before the addition of the new module would not need to be recompiled, but they also would not have access to the new module. The programs using the previous version of the service program would still work using the exported modules under the STRPGMEXP/ENDPGMEXP PGMLVL(*PRV) paired grouping.

OK, now the groundwork has been laid. By now, you may be asking yourself, “How do I use this stuff?” In Figure 2, you can see a sample program calling the CenterFld procedure with an EVAL statement. You could compile this program with the Create Program (CRTPGM) command and specify SRVPGM(TOOLS), and the program would compile. But if you are going to create multiple service programs in your applications, it’s better to use a binding directory when compiling the program. If you put all of your service programs in a binding directory and specify BNDDIR(TOOLBNDDIR) on the CRTBNDRPG command, the compile process will find the service program.

Creating a binding directory is easy. Just use the Create Binding Directory (CRTBNDDIR) command, as follows:


To add objects to the binding directory, use the Add Binding Directory Entry (ADDBNDDIRE) command:


Over the Wall!

We know what you’re probably thinking right about now, because we thought the same thing. This seems like an awful lot of work to write a simple function like centering a field. But once you have gone through the process, it’s really not that difficult. And the payoff is reusable, maintainable, modular code. As you can see in Figure 2, these modules are almost as easy to use as built-in functions (BIFs). After all, if you want to learn to hit home runs, you have to spend some time in the batting cages.

References and Related Materials

ILE RPG for AS/400 Programmer’s Guide (SC09-2507-02, CD-ROM QB3AGY03)






* procedure name: CenterFld


* procedure function: Return a centered field.

* GetAcro prototype
D/copy ileexample/prsource,CenterFld

P CenterFld B export
d CenterFld PI 32766 opdesc
d FieldToCtr 32766 options(*varsize)


* Prototype for CEEDOD (Retrieve operational descriptor)

*————————————————————————————————-D CEEDOD PR
D ParmNum 10I 0 CONST
D 10I 0
D 10I 0
D 10I 0
D 10I 0
D 10I 0

* Parameters passed to CEEDOD
D DescType S 10I 0
D DataType S 10I 0
D DescInfo1 S 10I 0
D DescInfo2 S 10I 0
D InLen S 10I 0
D HexLen S 10I 0

d X s 5 0
d y s 5 0
d z s 5 0
d ReturnFld s like(FieldToCtr) *

* Get length of 1st parameter passed to procedure
C CALLP CEEDOD(1 :DescType:DataType:
C DescInfo1 : DescInfo2: Inlen:
c eval X = InLen

* Find number of characters in field to be centered
c ‘ ‘ checkr FieldToCtr:X Y

c eval z = ((X - y) / 2) + 1

* Offset returned field by 1/2 the number of blank characters
c eval %subst(ReturnFld:z:Y) =
c %subst(FieldToCtr:1:Y)

c return ReturnFld
P CenterFld E

* program name: UseCenterF


* program function: Demonstrate how to use CenterFld.


* Must compile using the TOOLBNDDIR binding directory. The service

* program TOOLS is already in this directory and will be

* located and used automatically.




D***/copy ileexample/prsource,CenterFld

* This prototype is included here for clarity. You should use a

* version of the /COPY line shown above to bring in the prototype.

* The /COPY statement is all you need in a program to access the

* CenterFld procedure.

d CenterFld PR 32766 opdesc
d FieldToCtr 32766 options(*varsize)

dfield40 s 40
dCenterCon c const(‘Center this line’)

* Center within a 40-byte field—field size doesn’t matter
c movel CenterCon Field40
c eval Field40 = CenterFld(Field40)

c eval *inlr = *on

Figure 1: Use this module to center text within a field.

Figure 2: This sample program uses the CenterFld procedure.



Support MC Press Online

$0.00 Raised:

Book Reviews

Resource Center

  • SB Profound WC 5536 Have you been wondering about Node.js? Our free Node.js Webinar Series takes you from total beginner to creating a fully-functional IBM i Node.js business application. You can find Part 1 here. In Part 2 of our free Node.js Webinar Series, Brian May teaches you the different tooling options available for writing code, debugging, and using Git for version control. Brian will briefly discuss the different tools available, and demonstrate his preferred setup for Node development on IBM i or any platform. Attend this webinar to learn:

  • SB Profound WP 5539More than ever, there is a demand for IT to deliver innovation. Your IBM i has been an essential part of your business operations for years. However, your organization may struggle to maintain the current system and implement new projects. The thousands of customers we've worked with and surveyed state that expectations regarding the digital footprint and vision of the company are not aligned with the current IT environment.

  • SB HelpSystems ROBOT Generic IBM announced the E1080 servers using the latest Power10 processor in September 2021. The most powerful processor from IBM to date, Power10 is designed to handle the demands of doing business in today’s high-tech atmosphere, including running cloud applications, supporting big data, and managing AI workloads. But what does Power10 mean for your data center? In this recorded webinar, IBMers Dan Sundt and Dylan Boday join IBM Power Champion Tom Huntington for a discussion on why Power10 technology is the right strategic investment if you run IBM i, AIX, or Linux. In this action-packed hour, Tom will share trends from the IBM i and AIX user communities while Dan and Dylan dive into the tech specs for key hardware, including:

  • Magic MarkTRY the one package that solves all your document design and printing challenges on all your platforms. Produce bar code labels, electronic forms, ad hoc reports, and RFID tags – without programming! MarkMagic is the only document design and print solution that combines report writing, WYSIWYG label and forms design, and conditional printing in one integrated product. Make sure your data survives when catastrophe hits. Request your trial now!  Request Now.

  • SB HelpSystems ROBOT GenericForms of ransomware has been around for over 30 years, and with more and more organizations suffering attacks each year, it continues to endure. What has made ransomware such a durable threat and what is the best way to combat it? In order to prevent ransomware, organizations must first understand how it works.

  • SB HelpSystems ROBOT GenericIT security is a top priority for businesses around the world, but most IBM i pros don’t know where to begin—and most cybersecurity experts don’t know IBM i. In this session, Robin Tatam explores the business impact of lax IBM i security, the top vulnerabilities putting IBM i at risk, and the steps you can take to protect your organization. If you’re looking to avoid unexpected downtime or corrupted data, you don’t want to miss this session.

  • SB HelpSystems ROBOT GenericCan you trust all of your users all of the time? A typical end user receives 16 malicious emails each month, but only 17 percent of these phishing campaigns are reported to IT. Once an attack is underway, most organizations won’t discover the breach until six months later. A staggering amount of damage can occur in that time. Despite these risks, 93 percent of organizations are leaving their IBM i systems vulnerable to cybercrime. In this on-demand webinar, IBM i security experts Robin Tatam and Sandi Moore will reveal:

  • FORTRA Disaster protection is vital to every business. Yet, it often consists of patched together procedures that are prone to error. From automatic backups to data encryption to media management, Robot automates the routine (yet often complex) tasks of iSeries backup and recovery, saving you time and money and making the process safer and more reliable. Automate your backups with the Robot Backup and Recovery Solution. Key features include:

  • FORTRAManaging messages on your IBM i can be more than a full-time job if you have to do it manually. Messages need a response and resources must be monitored—often over multiple systems and across platforms. How can you be sure you won’t miss important system events? Automate your message center with the Robot Message Management Solution. Key features include:

  • FORTRAThe thought of printing, distributing, and storing iSeries reports manually may reduce you to tears. Paper and labor costs associated with report generation can spiral out of control. Mountains of paper threaten to swamp your files. Robot automates report bursting, distribution, bundling, and archiving, and offers secure, selective online report viewing. Manage your reports with the Robot Report Management Solution. Key features include:

  • FORTRAFor over 30 years, Robot has been a leader in systems management for IBM i. With batch job creation and scheduling at its core, the Robot Job Scheduling Solution reduces the opportunity for human error and helps you maintain service levels, automating even the biggest, most complex runbooks. Manage your job schedule with the Robot Job Scheduling Solution. Key features include:

  • LANSA Business users want new applications now. Market and regulatory pressures require faster application updates and delivery into production. Your IBM i developers may be approaching retirement, and you see no sure way to fill their positions with experienced developers. In addition, you may be caught between maintaining your existing applications and the uncertainty of moving to something new.

  • LANSAWhen it comes to creating your business applications, there are hundreds of coding platforms and programming languages to choose from. These options range from very complex traditional programming languages to Low-Code platforms where sometimes no traditional coding experience is needed. Download our whitepaper, The Power of Writing Code in a Low-Code Solution, and:

  • LANSASupply Chain is becoming increasingly complex and unpredictable. From raw materials for manufacturing to food supply chains, the journey from source to production to delivery to consumers is marred with inefficiencies, manual processes, shortages, recalls, counterfeits, and scandals. In this webinar, we discuss how:

  • The MC Resource Centers bring you the widest selection of white papers, trial software, and on-demand webcasts for you to choose from. >> Review the list of White Papers, Trial Software or On-Demand Webcast at the MC Press Resource Center. >> Add the items to yru Cart and complet he checkout process and submit

  • Profound Logic Have you been wondering about Node.js? Our free Node.js Webinar Series takes you from total beginner to creating a fully-functional IBM i Node.js business application.

  • SB Profound WC 5536Join us for this hour-long webcast that will explore:

  • Fortra IT managers hoping to find new IBM i talent are discovering that the pool of experienced RPG programmers and operators or administrators with intimate knowledge of the operating system and the applications that run on it is small. This begs the question: How will you manage the platform that supports such a big part of your business? This guide offers strategies and software suggestions to help you plan IT staffing and resources and smooth the transition after your AS/400 talent retires. Read on to learn: