Thursday, August 15, 2013

No More Number Indicators

I can remember in my first programming job being introduced to RPG III programs with a list of all the indicators used in the comments at the top of the program. While I admired the throughness of the documentation, I never did like that an indicator would only be used for one purpose. I prefered to use a few indicators for file Input/Output and check immediately afterwards if the indicator was *ON, for example:

01  * 99=End of file, 98=Error (record lock)
02 C                     READ FILE1                  9899
03 C           *IN99     IFEQ *ON
04  *
05  * 99=Not found, 98=Error (record lock)
06 C           KEY1      CHAINFILE1                9998
07 C           *IN99     IFEQ *ON

RPGLE/RPG IV introduced the "Operation Code Extender" which could replace the need for indicators for all of the operation codes. If I code the equivalent in RPG/free it could look like:

01 read FILE1 ;
02 if %eof ;

03 chain key1 FILE1 ;
04 if not(%found) ;

But when RPGLE/RPG IV was first introduced you still had to use numbered indicators to communicate with display and printer files. Fortunately this is no longer the case as you can use the Indicator Data Structure, INDDS, to give the numbered indicators in these types of files meaningful names.

In this example I am going to use a display file as our example. This works in exactly the same way for printer files.

The first thing I need to do is to add the INDARA to the top of the display file's source, with the other keywords that apply to the entire file, see below:

  A                                      DSPSIZ(24 80 *DS3)
  A                                      PRINT
  A                                      ERRSFL
  A                                      INDARA
  A                                      ALTHELP(CA01)
  A                                      HELP
   *-------------------------------------------------------
  A          R SFL01                     SFL

In the RPGLE/RPG IV source member I add the INDDS keyword into the File specification for the display file, see below, and the data structure with the same name as was given in the INDDS. In the data structure's subfields notice that the Data Type is 'N' for a indicator type field on lines 5-7 and 10-11.

01 F@SFL_DSPF CF   E             WORKSTN indds(IndDs)
02 F                                     sfile(SFL01:Z1RRN)
03  *******************************************************
04 D IndDs           DS
05 D   F3_Exit               3      3N
06 D   SflCtlDsp            30     30N
07 D   SflDsp               31     31N
08  * Errors
09 D   Errors               50     60A
10 D   ErrOpt               50     50N
11 D   ErrDept              51     51N

Now I can just move *ON and *OFF to the named indicators like this:

  // Intialize SFL
    SflCtlDsp = *off ;
    SflDsp = *off ;
    write CTL01 ;
    SflCtlDsp = *on ;

The error section of the IndDs data structure shows, on line 9, a trick I found. Rather than move *OFF all the indicators individually I can define a data structure subfield to be the same length as all of the error indicators. It must be defined as 'A', alphanumeric, as it is longer than one byte. I can then move all zeroes to it, which is the equivalent of moving *OFF to all the indicators in one step, see line 51 below:

01 Errors = *all'0' ;
02 exsr Validation ;
03 if (Errors <> *all'0') ;
04    iter ;
05 endif ;

06 begsr Validation ;
07   if ((Z1OPT <> '1')
08       and (Z1OPT <> '2')
09       and (Z1OPT <> '3')) ;
10     ErrOpt = *on ;
11   endif ;

12   setll Z1DEPT DPTMAST ;
13   if not(%equal) ;
14     ErrDept = *on ;
15   endif ;
16 endsr ;

In the subroutine Validation if any errors are found the appropriate indicator is turned *ON. When processing returns from the subroutine rather than test each indicator to see if it is *ON I can check if the Errors subfield is all zeroes, line 3, if it is not then an error has been found.

Now all the indicators are named there is not a need to list their function in the comments at the top of the program, or to puzzle about what an indicator is used for.

 

This article was written for IBM i 7.1, and it should work with earlier releases too.

16 comments:

  1. Great resource and examples! Next is to show the advanced version of multiple indicator ds arrays and using pointers to turn the 99 indicators into 99 times however many you need.

    ReplyDelete
  2. Wholeheartedly agree except for two things; your validation subroutine should be a sub procedure that returns an indicator (n) and your "if errors" trick becomes redundant as it becomes simply "if not validation" or better still call your sub procedure valid and it reads like proper English. Sub procedures offer so much more flexibility with return values and safety with locally scoped variables and prototyped calls that I have banned anyone from writing new subroutines in my team! The line clearing the errors array should be inside the sub procedure btw. I also prefer to qualify data structures so there is no chance of treading on variable names. This is more relevant where you are using multiple copy members to bring in common structure definitions of which your indicator structure may be one.

    ReplyDelete
  3. No doubt the author would truly implement in subprocedures - but this is easier to document and teach the concept - how to use named indicators when interacting with DSPF...

    ReplyDelete
    Replies
    1. I'd accept this reply if the "errors" character array hadn't been highlighted in the article as a neat trick to test for the presence of errors. It's unnecessary if you use a sub procedure with a return value and it makes the code much clearer.

      Delete
  4. Ok Simon, but I reserve the right....no, the need to use indicator 42 in special programs...to pay homage to Hitch Hikers Guide to the Galaxy and the meaning of life...ok, so yes, numbered boolean should be avoided at all costs!!

    ReplyDelete
  5. Robert PietrzykowskiAugust 17, 2013 at 2:41 PM

    When I write interactive programs I have a standard set of function keys that I use. F03 - Exit, F12 - Previous, F04 - Field Prompt etc. I like the *INKx indicators because I always know when a function key controls the execution of a block of code. So this would be nice to provide more descriptive function key indicators.

    ReplyDelete
  6. Numeric indicators never bothered me, until I ran out of them in an online order entry/invoice/credit memo, etc program....when I needed one, I had to hunt down where a numeric indicator was used, so I didn't use it on the same screen. Real pain.

    ReplyDelete
  7. I always hated them because IF *IN35;.... means absolutely positively nothing except testing to see if an indicator turned on...

    ReplyDelete
  8. I always wondered why they skipped *INKO (F15 key is *INKP)...Someone once told me in the early days of the S/38 that they couldn't get around the MicroCode so they just decided to skip 'O' and straight to 'P'

    ReplyDelete
    Replies
    1. I always thought it was because people got the letter "O" confused with the digit "0", and some models of dummy tubes and printers rendered them almost exactly the same.

      Delete
    2. That's probably it; it's easy to confuse O and 0. But I wonder why they didn't skip *INKI for the same reason?

      Delete
    3. One of the many unanswered trivial questions of this platform, whose answer probably lies in whether or not some IBM engineer had regular or decaf coffee on some morning in 1971.

      Delete
  9. Wow !! Will definitely try this.. 👍👍 Thanks for this wonderful tip !!

    ReplyDelete
  10. On pressing F3 in the screen, the F3_Exit does not turn on.. :(
    I have defined INDARA and CA03 in the dspf. Am I missing anything ?

    ReplyDelete

To prevent "comment spam" all comments are moderated.
Learn about this website's comments policy here.

Some people have reported that they cannot post a comment using certain computers and browsers. If this is you feel free to use the Contact Form to send me the comment and I will post it for you, please include the title of the post so I know which one to post the comment to.