12
Tue, Nov
5 New Articles

Go Indicatorless in RPG

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

Historically, indicators played an important part in RPG, as they controlled logic and file I/O. As RPG was modernized, however, the need to use indicators decreased and now RPG looks more like other programming languages. The time of indicator programming is over, so get ready to code the 21st century way!

What’s Wrong with Indicators?

One of the big problems with indicators is that there are only 99 of them. If your shop is like mine, you burned those up years ago on a big order-entry program that forced you to come up with crazy schemes just to manage it. The other problem with indicators is they are not self-documenting, so it is easy to forget what they’re being used for. There are several techniques I use to take care of DDS indicator functionality, such as highlighting a field, polling for a function key, displaying an error message using subfiles, and positioning a cursor. RPG IV itself provides many ways to help you avoid using indicators. (If you haven’t converted to RPG IV yet, what are you waiting for? See
“Breathing New Life into Old Code,” MC, February 2000 for some pointers on getting started.)

I’ve placed source code for a working customer file maintenance program and its related objects on the Midrange Computing Web site to implement and illustrate the techniques I’ll discuss in the following paragraphs. You can download my code at www.midrangecomputing.com/mc.

BIFs Are Better

The first place to start getting rid of indicators is in the C-specs. Traditionally, performing I/O on a file required one or more resulting indicators to be assigned to test the success of an I/O operation. In RPG IV you can use the %Eof, %Found, %Equal, and %Open built-in functions (BIFs) to test the results of an I/O operation. These BIFs are set to true (*ON) or false (*OFF) after the operation. %Eof stands for end of file, and it becomes true when a READx op code fails. If you chain to a file and want to know if you locked and retrieved the record, just check to see if the %Found is true instead of the hi resulting indicator. If you need to determine whether SETLL was successful, just check %Equal. In Figure 1, there are several examples of I/O using BIFs and their indicator equivalents.


Another important thing to mention is the %Error BIF. To use this BIF, you must code an (e) op code extender after the I/O op code. This BIF will be set to true when an error occurs in the op code being executed. If you are reading a file and %Error is true, then the cause of the problem could be a record lock or that the file was not open. To find the exact problem, you can use the %Status BIF to retrieve the error code. For more information on the %Status, see IBM’s ILE RPG for AS/400 Reference manual. Look at Figure 1 again and notice how the BIF operations document themselves. There’s no need to worry about reusing an indicator elsewhere in your code, and there’s no need to document what each indicator is doing, because each BIF is tied to the whole file in which you are working.

Taming DDS with P-fields

Display files traditionally use many indicators, so here’s the perfect place to replace them. In Figure 2, you can see that I have defined indicators for SFLNXTCHG, SFLDSP, and other keywords. Executing EVAL SFLNXTCHG = *On turns *IN08 on. Using field names instead of indicators makes source code self-documenting and easier to understand.

Instead of using an indicator to control the display of an I/O field, you can use program-to-system fields, or P-fields. P-fields allow you to control the attributes of a display field. To use P-fields, you need to code a unique field name for the field you are controlling. For example, if the field you are controlling is called CUST#, create a P-field called @CUST#. You can use any name you want, but I like to have a P-field name that is similar to the field it controls.

What capabilities do you want this field to have? Do you want to protect it so that it’s input-capable only? Do you want it to reverse image (RI) during an error? Do you want to make it blink? Or, do you want it to do all of these things? It doesn’t matter, because you have complete control over the field.

Figure 3 (page 98) contains a listing of 5250 panel constants; notice that each abbreviated constant name has a corresponding hexadecimal value. Each constant lets you control the field’s appearance and behavior. Suppose you have a field that needs to be input-capable, reverse image on an error, and blink when the user needs to be alerted to something; this would normally take three indicators, but you can now do this with just one controlling field. This method allows you to concentrate on your program logic and not on indicator management. For example, if I want the CUST# field to reverse image when I enter an incorrect customer number, I would set the controlling P-field @CUST# to constant RI (EVAL @CUST# = RI). Here, RI equals hexadecimal 21. As you can see in Figure 3, there are two sets of constant values: one set for protected fields (starting with PR) and another for unprotected fields. If you need to switch from input-capable to output- only, select constants beginning with PR; otherwise, select any constant from the unprotected section.

Continuing the CUST# example, I would need to code a P-field definition, as is done in Figure 4 (page 99). The P-field @CUST# is declared as a one-byte field with a P in position 38, and it needs to be inside the record I am displaying. The P-field @CUST#, when used by the keyword DSPATR, must be preceded by an ampersand (&) for your DSPF to compile. Your program will use P-field @CUST# to control the display of I/O field CUST# on the panel. Setting the control fields to UL (underline) or to normal prepares the fields for input. During validation, I will set the control fields to RI to show which fields are in error.

Another thing worth mentioning is that P-fields may also condition constants. For example, there may be fields you want to hide. When you hide these I/O fields, you may need to hide their captions as well. I will usually pick a P-field name for a text constant that has the input field name plus TX. If @CREDLM were the I/O field name, then @CREDLMTX would be the text caption P-field name. If @CREDLM (credit limit) is not


to be displayed, than @CREDLMTX could be set to ND or non-display, so that the text caption isn’t displayed when the I/O field isn’t showing.

For more information on P-field constants, see the DDS Reference manual. The code on the Web for this article contains a copybook called DSPATR, which contains all of the constants that the P-fields can use.

Positioning the Cursor

How do you position the cursor over a field in error without resorting to indicators? There is a keyword in DDS called CRSLOC (see Figure 4). This keyword has two 3-byte fields, which are both zoned-decimal hidden fields that control the row and column positioning of the cursor. The cursor will be positioned to whatever row and column number is sent to the DDS from the RPG program. For example, if CUST# had a bad customer number, I would send the proper coordinates to CRSLOC by setting hidden fields ROW# and COL# to force the panel’s cursor over this field.

How do you know the row and column number values for CUST# or, for that matter, for any other field? Number values for a field can be found using a service program I wrote called RTNFLDLOC.

RTNFLDLOC uses a system API called QDFRTVFD. This is a hard API to use and way beyond the scope of this article (see “Unravel the Display File Maze,” MC, January 2000), but using the service program itself is simple. The basic call to RTNFLDLOC is as follows:

CALLP RtnFldLoc(

ROW#: COL#:

fieldname:

panel record name:

File Name)

Two optional parameters, library name and ForceSize, may be passed after the file name parameter. Library name defaults to *LIBL; this is the library where the display file is located. The ForceSize parameter addresses panel width. This parameter forces a row/column calculation to be based on an 80-byte or a 132-byte panel. Normally, a panel is either designed to be 80 bytes or 132 bytes, and RTNFLDLOC can determine how to calculate the row and column automatically. If the panel width is defined by DSPSIZ (27 132 *DS4 24 80 *DS3) and you are using *DS3 or *DS4 indicators on your fields, then you must decide what to instruct RTNFLDLOC to do. Pass in a 3 to force an 80-byte column/row calculation for a field with a *DS3 indicator, when the default is 27-132 size and you need the *DS3 size. Pass a 4 for a field with *DS4, when the default is 24-80 size. The INFDS can tell you the size of the default panel. Positions 152 and 153 tell the number of rows—24 for an 80-byte panel, and 27 for a 132-byte panel. Positions 154 and 155 specify the number of columns, which is 80 or 132. With this in mind, when you need the *DS3 or *DS4 field’s position, just send in the correct value to the parameter.

Which Function Key Was Pressed?

You may be wondering how to know when the Enter key or function keys have been pressed. DDS doesn’t support an ENTER keyword on which you can attach an indicator, but your program can detect the Enter key, function keys, and other special-usage keys through the INFDS attached to your WORKSTN file. First, you should have all of the function key keywords (such as CF01 and CF02) coded in the file or record section of the DDS for this method to work (see Figure 4). Next, there is a byte in the INFDS at position 369 called AID, or Attention Indicator. After the panel has been read, the AID byte will contain a hexadecimal number corresponding to a function or editing key (such as Enter or Print). If you need to know whether the F3 key was pressed, just compare the AID byte to


the F3 constant. If you are reading a subfile and need to know whether the operator paged up or down, simply compare the AID byte to the roll-key constants. I have created a copybook, called FNKEYS, which is also in the downloadable code. This copybook includes constants for all the function keys, Enter, Page up, Page down, and so on. Using this method, all of the logic for these special keys is kept in the program to avoid using indicators.

Send Out an SOS

As I mentioned, I use message subfiles to display user error messages. I do this to avoid assigning indicators in the DDS to display a particular message. Message subfiles are displayed at the bottom of the panel in conjunction with the reverse image field in error. There’s nothing special to remember about how to code a message subfile; the source code never changes and can be copied from program to program.

For message subfile DDS, you must have the SFLPAG, SFLDSP, SFLDSPCTL, and SFLSIZ keywords in the subfile control record. SFLPAG tells how many subfile messages to display at a time, SFLDSP and SFLDSPCTL display the subfile and control record, and SFLSIZ is the number of records in the subfile.

SFLEND is the one keyword in the SFL control record that must have an indicator. SFLEND generates the plus sign or More... message that tells you when there’s more than one record to view. Other keywords that typically need indicators are those used for subfile control mechanics. You must have these keywords in the record portion of the subfile: SFLMSGRCD, SFLMSGKEY, and SFLPGMQ. SFLMSGRCD indicates the line number to start displaying messages. SFLMSGKEY allows your program to assign a key to the subfile message record. The field name specified in positions 29 through 39 in the DDS used for subfile message selection is not important for our purposes, but a name is still required. The SFLPGMQ keyword in the subfile record contains the name of the program message queue. A program message queue is typically where the system sends error messages about your program. In this case, you can use the queue to display your messages. SFLPGMQ (10) means that a 10-byte field is generated. The value 10 is the default and is not needed. The only other size available is 276.

To send a message to a message subfile, use the QMHSNDPM API, as I did in the SendSFLMsg service program module, or call a CL program or module that executes the Send Program Message (SNDPGMMSG) command. The service program I have created is called SFLMESSAGE and is available as part of the downloadable code that accompanies this article. SFLMESSAGE contains two modules, SendSFLMSG and ClearSFLMsg. ClearSFLMsg removes the records written to the subfile message queue, and SendSFLMSG writes them. Whenever I encounter an error during the validation of an input field, I not only reverse image the field but I also send a message to the subfile message queue describing the error. Using a subfile message queue lets you avoid having to hard code indicators in the DDS, and it gives full control to the program. You can either send a text message from the program to the subfile, or you can send a message ID, message file, and library. I choose to store error messages in an array and then retrieve and send them to the subfile as necessary. As mentioned before, the basic DDS code never changes and can be used in other programs.

Put It Together

Now that you know the techniques for indicatorless programs, here is the basic logic for indicatorless application programs:
1. Display the panel.

2. Press Enter or a function key on a panel. This panel has fields that are input-capable and its displays are controlled by P-fields.


3. Clear the subfile message queue.

4. Examine the AID byte, and determine whether a function key or the Enter key was pressed. Check to see if it is a valid function key for this program.

5. Reset all fields controlled by P-fields back to their default settings (e.g., underline for input fields [UL] or normal for constants).

6. Validate the controlled I/O fields and reverse image the fields in error. Position the cursor to the first error. Make sure to use %FOUND or any of the other %BIF as needed.

7. Send the error messages for each field in error to the SFL message queue.

8. Redisplay the panel and start again, or update the file and exit.

MNTCUS, the sample program I’ve placed on the Web, is a simple and straightforward maintenance program with no indicators.

MNTCUS uses P-fields to prompt for a customer number while making the other fields invisible. Once validated, it displays the customer details and allows you to change them. Additionally, the program verifies the function keys pressed. If a function key is invalid, the program sends an error message and redisplays the panel, but if all is OK, it allows you to cancel back to the previous panel, exit the program, or continue. If the data is invalid, MNTCUS reverse images each invalid field, positions the cursor, and sends an error to the message subfile. Download the code, follow the directions in the COMPILE source member, and take a good look at MNTCUS. Soon you’ll know how to make your own programs go indicatorless.

REFERENCES AND RELATED MATERIALS

• “Breathing New Life into Old Code,” Paul Ladouceur, MC, February 2000
• ILE RPG for AS/400 Programmer’s Guide (SC09-2507)
• ILE RPG for AS/400 Reference (SC09-2508)
• OS/400 DDS Reference V4R4 (SC41-5712-03)
• “Unravel the Display File Maze,” Gene Gaunt, MC, January 2000


***************************************************

* Traditional Way of Handling I/O

***************************************************

C CusKey Setll Customer 5350

C If *IN50

C Do *Hival

C CusKey Reade CustomerR 5351

C If *IN51

C Leave

C Endif

C If *IN53

C Message1 Dsply

C Leave

C Endif

C CrdKey Chain CreditCdR 5253

C If *IN52 = *On or *IN53

C Message2 Dsply

C Leave

C Endif

C Enddo

C Endif

***************************************************

* Indicatorless Way

***************************************************

C CusKey Setll(e) Customer

C If %Equal(Customer)

C Do *Hival

C CusKey Reade(e) CustomerR

C If %Eof

C Leave

C Endif

C If %Error

C Message1 Dsply

C Leave

C Endif

C CrdKey Chain (e) CreditCDR

C If Not %Found(CreditCD) or %Error

C Message2 Dsply

C Leave

C Endif

C Enddo

C Endif

Figure 1: BIFs beat indicator-laden code hands down!

* Declare Named Indicators

DIndicators DS Based(IndicatorP)

D SFLNXTCHG 8 8

D SFLCLR 40 40

D SFLCTLDSP 41 41

D SFLDSP 42 42

D SFLINZ 43 43

DIndicatorP S * Inz(%Addr(*In))

Figure 2: Indicators deserve to have meaningful names.


* RI=Reverse Image, HI=Hi Intensity, BL=blink, UL=Underline

* ND=Non Display

* NON Protect fields

d Normal c const(x'20')

d RI c const(x'21')

d HI c const(x'22')

d HIRI c const(x'23')

d UL c const(x'24')

d ULRI c const(x'25')

d ULHI c const(x'26')

d ND c const(x'27')

d BL c const(x'28')

d BLRI c const(x'29')

d BLHI c const(x'2A')

d BLHIRI c const(x'2B')

d BLUL c const(x'2C')

d BLULRI c const(x'2D')

d BLULHI c const(x'2E')

* Protect field

d PRNormal c const(x'A0')

d PRRI c const(x'A1')

d PRHI c const(x'A2')

d PRHIRI c const(x'A3')

d PRUL c const(x'A4')

d PRULRI c const(x'A5')

d PRULHI c const(x'A6')

d PRND c const(x'A7')

d PRBL c const(x'A8')

d PRBLRI c const(x'A9')

d PRBLHI c const(x'AA')

d PRBLHIRI c const(x'AB')

d PRBLUL c const(x'AC')

d PRBLULRI c const(x'AD')

d PRBLULHI c const(x'AE')

Figure 3: Using system-defined hexadecimal constants is a good way to eradicate indicators.


A**** For the full source code see MNTCUSFM ****

A DSPSIZ(24 80 *DS3)

A PRINT

A CF01

A CF02

. . . . Other Functions keys DECLARED . . .

A

A CF24

A PAGEDOWN

A PAGEUP

A*A R PANEL

A*A RTNCSRLOC(&RCD &FLD &POS)

A CLRL(10)

A CSRLOC(ROW# COL#)

A OVERLAY

A RCD 10A H

A FLD 10A H

A POS 4S 0H

A ROW# 3S 0H

A COL# 3S 0H

A @CUST# 1A P

A @CUST#TX 1A P

. . . . Other P Fields Declared . . .

A @CREDLM 1A P

A @CREDLMTX 1A P

A TITLE 30A O 1 25DSPATR(HI)

A 1 60DATE

A EDTCDE(Y)

A 1 70TIME

A 3 2'Customer Number :'

A DSPATR(&@CUST#TX)

A CUST# R B 3 20REFFLD(CUSTOMERR/CUST# CUSTOMER)

A DSPATR(&@CUST#)

A 3 30'Credit Code:'

A DSPATR(&@CREDCDTX)

A CREDCD R B 3 44REFFLD(CUSTOMERR/CREDCD *LIBL/CUSTOA MER)

A DSPATR(&@CREDCD)

A DESC R O 3 47REFFLD(CREDITCDR/DESC *LIBL/CREDITCA D)

A DSPATR(&@DESC)

A 5 2'Customer Name :'

A DSPATR(&@CNAMETX)

A CNAME R B 5 20REFFLD(CUSTOMERR/CNAME *LIBL/CUSTOMA ER)

A DSPATR(&@CNAME)

A 7 2'Address :'

A DSPATR(&@CADD1TX)

A CADD1 R B 7 20REFFLD(CUSTOMERR/CADD1 *LIBL/CUSTOMA ER)

A DSPATR(&@CADD1)

A 8 3'City/State/Zip'

A DSPATR(&@CADD1TX)

A CCITY R B 8 20REFFLD(CUSTOMERR/CCITY *LIBL/CUSTOMA ER)

A DSPATR(&@CCITY)

A CSTATE R B 8 37REFFLD(CUSTOMERR/CSTATE *LIBL/CUSTOA MER)

A DSPATR(&@CSTATE)

A CZIP R B 8 40REFFLD(CUSTOMERR/CZIP *LIBL/CUSTOMEA R)

A DSPATR(&@CZIP)

A 11 2'Credit Limit:'

A DSPATR(&@CREDLMTX)

A CREDLM R B 11 16REFFLD(CUSTOMERR/CREDLM *LIBL/CUSTOA MER)

A DSPATR(&@CREDLM)

A EDTCDE(Z)

A 23 3'F3=Exit'

A 23 23'Enter=Continue'

A 23 41'F12=Cancel'

A*A R MSFL

A*A SFL

A SFLMSGRCD(24)

A MSGKEY SFLMSGKEY

A PGMNAM SFLPGMQ(10)

A R MSFLC

A SFLCTL(MSFL)

A LOCK

A OVERLAY

A SFLSIZ(50)

A SFLPAG(1)

A N26 SFLEND

A SFLDSP

A SFLDSPCTL

A SFLINZ


A PGMNAM SFLPGMQ

Figure 4: Display files are among the heaviest users of indicators.


Click here to download code.

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: