29
Fri, Nov
0 New Articles

Practical Examples of Code Without Indicators, Part I

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

You've heard a lot about coding without indicators and perhaps even seen some code, but this article will show how the techniques can make you a better developer.

 

RPG programmers have a long and storied relationship with indicators. Certainly, it can be argued that without indicators there would be no RPG. However, it's been argued for some time now that we should write RPG with no indicators. In fact, some would argue that the only indicator you should ever see in an RPG program is *INLR: the last record indicator, which we still use to signal the end of a program. But does removing indicators have a real, practical benefit, or is it more of a theoretical exercise in "better programming"? This article provides a real example that proves the usefulness of the indicator-free programming style.

Change for the Sake of Change?

If you know me at all, you know I am not an advocate of change for the sake of change. I've been upset with some of IBM's moves over the years--no pun intended, even though the banishment of the MOVE opcode from the /free syntax is an example of a bad change in my opinion, and it's one that rankles deeply.

 

I often find myself at odds with compiler developers and computer science experts. On a mailing list awhile back, I had a serious debate with a couple of folks, one in which I took a minority position. The argument was somewhat esoteric and had to do with the fact that new, larger VARYING fields would require a change in how those fields were defined internally by the compiler. The crux of my argument was that the VARYING keyword should have a default that allows old programs to work without change, even if the compiler has to do magic under the covers for larger fields. I got a lot of grief for that position, but my point was simple: the compiler should always err on the side of making programming easier for everyday application developers rather than catering to those who push the envelope. And for once, I was vindicated; even though I was roundly criticized by the experts, in the end IBM implemented the VARYING keyword exactly how I suggested.

 

I bring this up as a preface to what I'm going to present to you in this article: a real, practical way to use indicator-free programming to make your job easier (especially in the brave new world of /free syntax). No doubt you've heard that indicators are bad and that we should strive to rid our programs of them, but in this article I'm going to take on one of the most difficult challenges to that notion--namely, how to handle display files--and show that indicator-free programming is not only possible, but even easier to code and maintain.

On to the Code

I've got a lot of ground to cover here, so I'm going to dispense with the pleasantries and get right down to business. Let me start off by explaining what I'm going to do and why, then move to the how, and then finish off with the ultimate benefits of the approach.

 

Of course, I have to lay the groundwork just a little, but I'll try to be brief. RPG has supplied us with a number of built-in functions (BIFs) that allow us to write RPG code without indicators. BIFs such as %eof come immediately to mind. However, no such advance has been made in the coding of Data Definition Specifications, or DDS. DDS is the way we describe display files, very much the way that HTML describes Web pages. And while much of the communication between the program and the display file is done through standard numeric and alphanumeric fields, many things are done primarily (and in some cases solely) through the use of indicators.

 

Three classes of interaction are most prevalent. First is the identification of which command key the user hit. This is so important that RPG actually used a separate set of indicators outside the normal 99 that were dedicated exclusively to command keys. Let me lead off by saying that one way to avoid the use of indicators for command keys is to use the workstation informational data structure (or INFDS) and the AID byte that is contained in that data structure. By testing the AID byte for specific hexadecimal values, you can determine which key was pressed, and this is a technique that many people advocate. I've never been partial to that technique; instead, I use numbered indicators 01 through 24 to handle the corresponding function keys (and then 25, 26, and so on to handle any additional command keys, such as Page Up and Page Down).

 

But Aren't Those Indicators?

Well, yes, they are! However, by exploiting a wonderful technique known as the indicator area, I can actually send those indicators back and forth without ever once having to reference them using the *IN syntax that we're trying to eliminate (I won't even dignify left-hand indicators). Instead, by using a combination of the INDARA and INDDS keywords (INDARA is used in the display file, while INDDS is used in the RPG program), I can create a data structure with named indicators to communicate with and control my display file.

 

Let's start with one of the most common uses of indicators, one that we can't get away from: using indicators for controlling a subfile. I often use a setup that looks like this:

 

     A N31                                  SFLCLR

     A  31                                  SFLDSPCTL

     A  32                                  SFLDSP

 

Note that I'm using two indicators to control the subfile. First is 31, which if off clears the subfile and if on displays the subfile control record. In my experience, you're either doing one or the other; you clear the subfile prior to loading it and displaying it. In this case, though, I use a different indicator (32) to display the subfile itself. By doing this, I can choose to not display the subfile if it is empty but still display the subfile control record. This is a very common practice.

 

In the bad old days, I could use a MOVEA instruction to set the indicators to one of the three possible states. MOVEA '00' *IN,30 would set off both indicators 31 and 32, thus preparing the subfile to be loaded. After performing a WRITE to the subfile control record, I would set indicator 31 on in preparation for the WRITE that would actually display the screen. I would then load the subfile, and only if one or more records were written would I then set indication 32 on.

 

The code would be relatively simple:

 

     C                   MOVEA     '00'          *IN(31) 

     C                   WRITE     CTL1

     C                   MOVE      *ON           *IN31 

     C                   DOW       (some condition)

     C                   WRITE     SFL1

     C                   MOVE      *ON           *IN32 

     C                   ENDDO

     C                   WRITE     CTL1

This would do what we needed to do. It would clear the subfile (the first write to CTL1) and then load the subfile, setting on first indicator 31 to display the control record, and then, if any records were to be written to the subfile, it would set on indicator 32. Note that in this case I'm skipping the code that actually loads the fields of the records and also the code that increments the relative record number for the subfile; I'm concentrating solely on the indicator code. You may recognize the use of the MOVEA opcode. This opcode is not available in /free syntax. And while the MOVE instruction can often be replaced with an appropriately coded EVAL opcode, there simply is no equivalent for the MOVEA.

 

However, I have a way around that limitation. By using an INDDS, I can do a little bit of magic. First, on the file specification I identify the INDDS data structure:

 

     FIN0101D   CF   E             WORKSTN SFILE(SFL1:Sfl1RR#)

     F                                     INDDS(WS_INDS)

Next, I specify the indicator data structure, in which I give indicators 31 and 32 names. More importantly, though, is the fact that I group them together and then create a couple of constants that I'll use to load the indicators:

 

     DWS_INDS          ds            99

     D WS_SflCtlDsp           31     31n

     D WS_SflDsp              32     32n

     D WS_Sfl                 31     32

    

     D CWS_SflClear    c                   '00'

     D CWS_SflEmpty    c                   '10'

     D CWS_SflData     c                   '11'

 

This not only creates the data structure that communicates between the RPG and the display file, but it gives names to the two indicators, 31 and 32, which control the clearing and display of the subfile. Next are the constants, which all start with CWS, each one defining a specific state of the two indicators. For example, CWS_SflClear is used when the subfile is to be cleared. By doing this, I can go to the following /free code:

 

       WS_Sfl = CWS_SflClear;

       write CTL1;

       WS_Sfl = CWS_SflEmpty;

       dow (something);

         write SFL1;

         WS_Sfl = CWS_SflData;

       enddo;

       write CTL;

 

As you can see, I don't have any ties to indicators 31 and 32 anymore; nor do I have to resort to hard-coded values such as '00' or even *ON and *OFF. Instead, I set the variable WS_Sfl to the appropriate state variable and then execute my WRITE instruction. Since WS_Sfl extends from positions 31 to 32 of the data structure, updating that value will set both of those indicators accordingly.

 

Other Uses of the Technique

So that gives you the basic technique. Identify your indicators intelligently, making sure that indicators that are to be set at the same time are adjacent numerically. This allows you to create a single field over multiple indicators and then set them all at once with a single EVAL statement.

 

But this technique is not limited to subfile control. Another situation I find useful is in just about any standard maintenance program:

 

     A                                  4  5'Item Number'

     A                                      COLOR(BLU)

     A            XOITEM        15A  B  4 25

     A  41                                  DSPATR(RI PC)

     A  61                                  DSPATR(PR)

     A N61                                  DSPATR(UL)

     A                                  6  5'Description'

     A                                      COLOR(BLU)

     A            XODESC        30A  B  6 25

     A  42                                  DSPATR(RI PC)

     A  62                                  DSPATR(PR)

     A N62                                  DSPATR(UL)

     A                                  7  5'Manufacturer Code'

     A                                      COLOR(BLU)

     A            XOMANU        15A  B  7 25

     A  43                                  DSPATR(RI PC)

     A  63                                  DSPATR(PR)

     A N63                                  DSPATR(UL)

 

Here is a panel with three fields: item number, description, and manufacturer code. Item number is the key. I use this all the time: indicators from 41-59 are used to identify errors, while indicators 61-79 are used to protect fields. But, through the use of the INDDS, I can do a little magic:

 

     DWS_INDS          ds            99

(...)

     D WS_Errors              41     60n   DIM(20)

     D WS_ProtKeys            61     61n   DIM(1)

     D WS_ProtData            62     80n   DIM(19)

Note that I identify all the error indicators in one array, and then I split the protection indicators into two separate arrays, for key fields and data fields. This allows me to do several things. Here are some examples:

 

       WS_Errors = *off;   // Clear all errors

By setting the array to *OFF, all error indicators are cleared. 

 

       WS_Errors(2) = *on;   // Identify field 2 as in error

Next, I can set an error using a simple field number. I could even use a named constant to make it more self-documenting:

 

       WS_Errors(C_DESC) = *on;   // Error in DESCRIPTION field

This is my favorite, though. It's now incredibly easy to protect the various fields, depending on what I am trying to do:

 

       select;

         when opcode = C_ADD or opcode = C_COPY;

           WS_ProtKeys = *OFF;

           WS_ProtData = *OFF;

         when opcode = C_CHANGE;

           WS_ProtKeys = *ON;

           WS_ProtData = *OFF;

         when opcode = C_DELETE or opcode = C_VIEW;

           WS_ProtKeys = *ON;

           WS_ProtData = *ON;

       endsl;

 

So now, if I am adding or copying a record, both the key and data fields are input-capable. If I am changing a record, the key fields are protected, but the data fields are editable. And if I'm deleting or viewing a record, all fields are protected. That's a pretty slick way of doing things, I think.

Is This the Only Way to Get Rid of Indicators?

No, there are other techniques. Attributes can be specified using special program-to-system fields. Cursor position can be done the same way. But I like the simplicity of the INDDS data structure. By using consistent naming, I have created a skeleton program that will adapt itself to different numbers of key and non-key fields without any work on my part other than laying out the INDDS data structure properly.

Being Indicator-Free

As demand dictates, I'll write additional articles to touch on some other indicators you can get rid of without a lot of effort. But for now, you can begin your journey to an indicator-free programming style.

Joe Pluta

Joe Pluta is the founder and chief architect of Pluta Brothers Design, Inc. He has been extending the IBM midrange since the days of the IBM System/3. Joe uses WebSphere extensively, especially as the base for PSC/400, the only product that can move your legacy systems to the Web using simple green-screen commands. He has written several books, including Developing Web 2.0 Applications with EGL for IBM i, E-Deployment: The Fastest Path to the Web, Eclipse: Step by Step, and WDSC: Step by Step. Joe performs onsite mentoring and speaks at user groups around the country. You can reach him at This email address is being protected from spambots. You need JavaScript enabled to view it..


MC Press books written by Joe Pluta available now on the MC Press Bookstore.

Developing Web 2.0 Applications with EGL for IBM i Developing Web 2.0 Applications with EGL for IBM i
Joe Pluta introduces you to EGL Rich UI and IBM’s Rational Developer for the IBM i platform.
List Price $39.95

Now On Sale

WDSC: Step by Step WDSC: Step by Step
Discover incredibly powerful WDSC with this easy-to-understand yet thorough introduction.
List Price $74.95

Now On Sale

Eclipse: Step by Step Eclipse: Step by Step
Quickly get up to speed and productivity using Eclipse.
List Price $59.00

Now On Sale

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: