25
Wed, Dec
0 New Articles

Subprocedures: A Step in the Right Direction!

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

While some may think that RPG is dead and periodically call for its burial, an in- depth study of the anatomy of subprocedures reveals not a corpse, but rather a thriving language that is finally getting the attention from IBM that it deserves. However, to keep IBM on a continued path of improvement and enhancement and to ensure that support for the language does not languish in the face of the recent Java enthusiasm, we must push the current features to the limit and keep demanding more from IBM.

This article encourages the exploitation of subprocedures (by example) and discloses the important elements of subprocedures (prototyping, interface definition, and argument options just to name a few) and explains how you can use them to replace functions that you may have previously implemented with standard “/COPY” source code routines, such as text- or string-centering functions. As such, our function will be named StrCenter, short for String Center.

What’s the Difference Between /Copy Source and Subprocedures?

Before I disclose the similarities between /COPY routines and subprocedures, I’ll review an important difference: /COPY routines enable reuse of standard source code routines, but subprocedures enable binary reuse of standard routines or functions—reusability without recompilation. This reuse is made possible with the introduction of ILE modules (object type *MODULE) on the AS/400. Modules are not executable objects, but they can be bound with other modules to create executable programs.

ILE modules are created with the Create xxx Module (CRTxxxMOD) command, where xxx identifies the language of the source code module used with the CRTxxxMOD command. For example, CRTRPGMOD is used to create an ILE RPG (or RPG IV) module, whereas CRTCMOD is used to create an ILE C module. The source type for your subprocedure must be RPGLE in order to be used to create an ILE RPG module. To create

the RPG module, you use option 15 from PDM instead of the typical 14 option, which creates a program.

I chose the text- or string-centering function to demonstrate subprocedures, because it is both simple and usable, and most of us have, at some time or another, written a function or subroutine to center text. However, even if you haven’t written such a function, you can easily imagine what it would take to accomplish this task and thus intuitively accept what you read—and acceptance is half of understanding what is presented. What is left is the material relevant to understanding subprocedures.

Subprocedures give us in RPG what we do not get with subroutines: the capability to pass parameters to and receive values from them. For instance, in the example case, I need to pass to the subprocedure a “reference to” (more on this later) a string of characters (a text field) and the length of the receiving variable (which may or may not be the same as the passed string variable). I will be receiving the centered text in the named variable for my EVAL assignment statement. (For an example of the StrCenter function, see “RPG Building Blocks: Centering a String of Text” elsewhere in this issue). This is the algorithm implemented by the StrCenter: The definition of what is passed to a subprocedure (number and type of parameters) is defined by the subprocedure prototype. But what is prototyping?

Prototyping…Sign in, Please

In other languages, such as C, the notion of prototypes is a familiar one. However, to the veteran RPG programmer, this can be an alien concept—but, as you will see, a welcome one, given the benefits of subprocedures.

What is a prototype? A prototype discloses the interface of a subprocedure to the calling program or subprocedure. An interface, in any language, is the mechanism through which we communicate (i.e., pass information to and from functions). The ILE RPG compiler, to provide compile-time type checking of arguments passed to and returned from the subprocedure, uses the prototype as a way to ensure that the proper number and types of arguments are passed, as defined in the procedure interface for the subprocedure. In essence, the “signature” for the subprocedure is defined by the subprocedure name, number of arguments, return values, and the types of arguments and return values provided by the prototype.

I place all of my prototypes into a file called SYSINC (system includes). However, you may place it in the same source file as your subprocedure (which is likely to be QRPGLESRC). Let’s begin with the compiler directives (Label A in Figure 1) specified at the top of the source for my prototype definition. I have defined a compiler condition variable, StrCenterHCopied, that will be created when the first /COPY encountered that includes this definition is read. This avoids the compiler errors that result if another subprocedure or module has already prototyped it for compilation.

The PR statement (or prototype definition statement) shown at Label B identifies and defines any value to be returned by the subprocedure. This must be the maximum length of receiver variable that can be returned by the subprocedure. In this case, I limit the string length to 256 characters. Additionally, I have defined that OPDESC (the operational descriptor) be passed on the call to the subprocedure. This will be used primarily to retrieve the length of the referenced variable specified for argument 1. Immediately following this statement are the parameters that will be passed to the StrCenter function (Labels C and D). These parameters can be given names or not; they are inconsequential to this discussion.

Named Receiver Variable = StrCenter(UncenteredText :

SizeOfNamedReceiverVariable)

What I mean by that is, the names I refer to them as are the local names I define in the subprocedure, not the names defined in the prototype.

The compiler is interested only in the number and type of parameters, not the names. However, if names are not given to the arguments of the prototype, you should at minimum document their usage in a set of formal comments with the /COPY prototype code.

I have defined two parameters: a character variable of variable size up to a maximum of 256 characters (Label C) and a five-digit packed numeric field with zero decimal precision (Label D). I have defined argument 1 with the optional keyword Options(*VARSIZE) to tell the compiler that I will pass character fields of varying lengths, as would be required for a useful text-centering utility. I have defined the second argument as a five-digit packed numeric field so that I may use it with the ILE CL command CALLPRC. Since ILE CL does not currently support integer data types, I cannot use the more-efficiently stored data type for passing the size of the receiver variable, if I intend to call it from ILE CL programs. Otherwise, I recommend using integers to pass numeric values to subprocedures.

Note that the five-digit packed numeric field has been defined as a constant (CONST). This informs the compiler that this field is a read-only field and will not be changed by the subprocedure StrCenter. When creating your own subprocedures, it is useful to know that, by default, when you pass an argument to a subprocedure, you pass a reference to a defined variable, not the value of the variable. To pass the value of a variable, you must define the argument with the VALUE keyword appended.

You can define other argument constraints and preferences in addition to those presented in this article. They can be found under “definition-specification keywords” in the IBM ILE RPG Reference Guide.

Heart of the Function

Armed with an understanding of the prototype, let’s look at the implementation details of the StrCenter function. Figure 2 presents this code in its entirety.

The first statement, a control specification with the NoMain keyword (Label E), informs the compiler not to generate cycle code for this module. RPG is a fixed-cycle language (whether we use the cycle or not). Because using the RPG cycle to call the subprocedure would result in undue overhead, I tell the compiler that no main procedure is required. To that effect, I code a NOMAIN keyword in the H-spec. The next statement (Label F) is a /COPY statement to include the prototype source statements in the module compilation. The subprocedure definition begins with the StrCenter Begin statement, denoted by the B in column 24 of the P-spec. There are two P-specs, one to begin the subprocedure and one to end it. The Export (Label G) keyword definition makes the subprocedure available to other programs and subprocedures; otherwise; it is available only within the current module.

Procedure Interface and Local Variables Definition

Next, I define the procedure interface (Label H). The procedure interface defines parameters passed to the subprocedure and any values returned. These parameters and values must match the prototype defined earlier. The PI statement is also where I give local names to the parameters.

Then, I define any local variables (Label I) needed to perform the string-centering function and return any values. Local variables are accessible only within the subprocedure in which they are defined. So, I can have a variable Title defined in the calling program as a 40-character field and defined in the subprocedure with the same name as a 256-character field. Thus, the StringOut variable could be named Title, and no conflicts would arise.

At Label I, you will also see the variable InLen defined as a 10-digit signed integer for the receiver from a call to the ILE API CEEDOD (Label J). CEEDOD retrieves the operational descriptor information for the first argument passed to this subprocedure so that the subprocedure references only the data passed to it. This facilitates the %LEN(%TRIMR(WorkString)) statement in Label K that trims blanks to the right of significant referenced variable data and then returns the length of the nonblank character string.

Finally, I define the subprocedure logic. In the first part of this logic, I determine the actual number of characters in the string parameter passed. The logic in Label K is coded for V3R7 and later releases of RPG; it can be replaced by the code in Figure 3 for prior releases. The CHECKR op code returns the actual length (number of nonblank characters) of the variable passed as the argument; whereas, the %SIZE built-in function returns the size of the variable passed as an argument, regardless of the data contained within the variable.

The remainder of the code in Figure 2 deals with finding the difference between the midpoint for the receiver variable and the midpoint of the passed string variable for the purpose of positioning the string in the middle of the receiver (return) variable. The last statement of logic, RETURN %SUBSTR(StringOut:1:StrLength), returns the centered text variable (but only the number of characters it can support). The subprocedure ends on the P-spec with E in position 24.

To create the subprocedure module, run the CRTRPGMOD command, as described earlier. In the program that requires the centering function, include a /COPY statement like the one at Label F. Then, create another RPG module for the program. Finally, bind the two modules together in a single program using the Create Program (CRTPGM) command, specifying the program name and related modules that make up that program.

Put on Your Running Shoes…the Race Is On!

ILE RPG subprocedures are quite easy to implement, and they make the usually mundane task of writing yet another text-centering function fun! But don’t stop there. There are many other functions yet to be written, and IBM still needs to implement many features to make RPG competitive with other languages. For example, both C++ and Java have a construct called a class, which combines data with related methods (file descriptions with subprocedures). IBM’s current statement of direction is that the only changes it will make to RPG will be ones that make it “cooperate with” these other languages, such as C++ and Java. It doesn’t sound like IBM has overwhelming enthusiasm for giving RPG the internal support it needs to become RPG++. But if you think for a moment about how you could implement a class in RPG++, it might look something like that presented in Figure 4.

Instead of using the Export statement to designate a public function or data, public could make the class method exportable, while private functions and data could be accessed only by class methods defined as public.

While I am not recommending my example as the guide by which IBM should implement object-oriented RPG, one can see that it is not a stretch to believe IBM could create an object-oriented RPG if the company were sufficiently motivated.

IBM, if you’re listening, Java is a good long-term strategic direction for a portable AS/400 language, but don’t forget the language that made the AS/400 a success—RPG.

References

ILE RPG Programmer’s Guide (SC09-2074, CD-ROM QBJAQD01) ILE RPG Reference Guide (SC09-2077, CD-ROM QBJAQE01)

** Compiler Directives
*-

BEGIN LABEL A

/If Not Defined( StrCenterHCopied )
/Define StrCenterHCopied

/Else

/Eof

/ EndIf
END LABEL A

** Prototype for StrCenter Function.

*-

BEGIN LABEL B

D StrCenter PR 256A OPDESC
END LABEL B

BEGIN LABEL C

D 256A Options(*VARSIZE)
END LABEL C

BEGIN LABEL D

D 5P 0 CONST
END LABEL D

**===============================================================

* To compile:

*

* CRTRPGMOD MODULE(XXX/STRCENTER) SRCFILE(XXX/QRPGLESRC)

*

*===============================================================

BEGIN LABEL E

H Nomain
END LABEL E

BEGIN LABEL F

D/COPY SysInc,StrCenterH
END LABEL F

*-

BEGIN LABEL G

P StrCenter B Export
END LABEL G

*-

BEGIN LABEL H

D PI 256A OPDESC

D StringIn 256A Options(*VARSIZE)

D StrLength 5P 0 CONST
END LABEL H

** 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

D 12A Options(*OMIT)

** Local function variables and return value definition.

*D StringOut S 256A INZ

D WorkString S 256A INZ

D NbrOfChar S 5P 0 INZ

Figure 1: StrCenter compiler directives and prototype

D Adjust S 5P 0 INZ
*

D DescType S 10I 0

D DataType S 10I 0

D DescInfo1 S 10I 0

D DescInfo2 S 10I 0
BEGIN LABEL I

D InLen S 10I 0
END LABEL I

*-

BEGIN LABEL J

C CALLP CEEDOD(1 : DescType : DataType :

C DescInfo1 : DescInfo2: InLen :

C *OMIT)
END LABEL J

C EVAL WorkString %SUBST(StringIn:1:InLen)
BEGIN LABEL K

C EVAL NbrOfChar %LEN(%TRIM(WorkString))
END LABEL K

C IF (NbrOfChar < StrLength )

C EVAL(H) Adjust = ( StrLength - NbrOfChar ) / 2

C IF Adjust > *ZERO

C EVAL %SUBST( StringOut:Adjust:StrLength) =

C % SUBST(%TRIML( WorkString):1:Inlen)

C ENDIF

C ELSE

C EVAL StringOut = %SUBST(%TRIML(WorkString):1:+

C StrLength )

C ENDIF

C RETURN %SUBST(StringOut:1:StrLength)

*PStrCenter E

*C* HiLoEq

C ‘ ‘ CHECKR StringIn:InLen:NbrofChar 6839
C IF (*IN39 = *ON AND NbrOfChar < StrLength)

PMyClass B CD } CD - Class Definition
D MyClassID 10I 0 Private } Data can only be accessed
D MyClassName 30A Private } by class methods.

P MyClass CM } CM - Class Method
D AClassID 10I 0 } Class ConstructorD AClassName 30A } Defaults to private access
C EVAL MyClassID = AClassID
C EVAL MyClassName = AClassName
C RETURN this } Reference to MyClass being
constructed

P SetName CM Public
D NewClassName 30A 0
C EVAL this.MyClassName = NewClassName

P GetName CM 30A Public
C RETURN this.MyClassName

PMyClass E

Figure 2: This subprocedure defines the string-centering function

Figure 3: This code is for releases prior to V3R7

Figure 4: RPG might look like this if it were an object-oriented language

BLOG COMMENTS POWERED BY DISQUS

LATEST COMMENTS

Support MC Press Online

$

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: