• The Four Hundred
  • Subscribe
  • Media Kit
  • Contributors
  • About Us
  • Contact
Menu
  • The Four Hundred
  • Subscribe
  • Media Kit
  • Contributors
  • About Us
  • Contact
  • Commands: Underused and Unappreciated

    February 16, 2011 Ted Holt

    As programming languages go, CL is not glamorous. Nevertheless, it is practical and effective, and it has some nice features. One of my favorite features is the ability to extend the CL language by creating my own commands. I have used this feature many times to great advantage over the years, and I am amazed that so many programmers have never written a command. In this article I discuss advantages of creating commands and give an example of how to do so.

    I have noticed that many shops use the CALL command exclusively to start execution of a program. CALL works in all instances and is often sufficient. However, you can write a command as an alternative interface to a program. Running the command is the same as calling the program, but the command has certain advantages. Here are some of them.

    Advantages of Commands over CALL

    1. Keyword parameters are easier to read than positional parameters.

    Let’s say you’re required to change a CL program. Which of the following two commands would you prefer to see as you read through the source code? Do you like the CALL version?

    CALL PGM(MYPGM) PARM('QCUSTCDT  QIWS      ' 'CUSTOMER  QTEMP     ' +
                       '*FIRST' 'CUSTOMER' '*REPLACE')
    

    Or the keyword version?

    MYCMD FROMFILE(QIWS/QCUSTCDT) TOFILE(QTEMP/CUSTOMER) +
            FROMMBR(*FIRST) TOMBR(CUSTOMER) MBROPT(*REPLACE)
    

    I vote for the keyword version, because it gives me a lot of information about what’s going on.

    2. When using keyword parameters, you don’t have to leave placeholders for unnecessary parameters.

    Suppose you only need to provide values for parameters 1, 2, and 10 on a call to program MYPGM. Which of the following do you like better?

    CALL PGM(MYPGM) PARM(&ENDDATE &COMPANY X X X X X X X CLOSE)
    
    
    MYCMD ENDDATE(&ENDDATE) COMPANY(&COMPANY) OPTION(CLOSE)
    

    Again, I prefer the second.

    3. Rules for parameter values are more relaxed when using a command than they are under CALL.

    Suppose program MYPGM requires one parameter–a two-digit packed decimal company number. To call this program from another program requires that the company number match in type and size.

    DCL        VAR(&COMPANY) TYPE(*CHAR) LEN(3)
    DCL        VAR(&NCOMPANY) TYPE(*DEC) LEN(2 0)
    
    CHGVAR     VAR(&NCOMPANY) VALUE(&COMPANY)
    CALL       PGM(MYPGM) PARM(&NCOMPANY)
    

    But if you call MYPGM via a command, the command processor converts the data to the required type and size for you.

    DCL        VAR(&COMPANY) TYPE(*CHAR) LEN(2 0)
    
    MYCMD      COMPANY(&COMPANY)
    

    Say goodbye to those annoying scratch variables that clutter up your code.

    4. If the command definition allows it, you may use expressions in command parameters. You may not use expressions in the PARM parameter of the CALL command.

    In this example, MYPGM requires three parameters. Suppose you wish to call MYPGM using parameter values extracted from a data area. Here’s how it’s done with CALL.

     DCL        VAR(&DATA) TYPE(*CHAR) LEN(1024)
     DCL        VAR(&PRTTXT) TYPE(*CHAR) LEN(30)
     DCL        VAR(&COMPANY) TYPE(*DEC) LEN(2)
     DCL        VAR(&CUSTOMER) TYPE(*DEC) LEN(6)
    
     CHGVAR     VAR(&COMPANY) VALUE(%SST(&DATA 101 2))
     CHGVAR     VAR(&CUSTOMER) VALUE(%SST(&DATA 103 6))
     CHGVAR     VAR(&PRTTXT) VALUE(%SST(&DATA 151 200))
    
     CALL       PGM(MYPGM) PARM(&COMPANY &CUSTOMER &PRTTXT)
    

    The same process is simpler when using a command that allows expressions.

    DCL        VAR(&DATA) TYPE(*CHAR) LEN(1024)
    
    MYCMD      COMPANY(%SST(&DATA 101 2)) +
               CUSTOMER(%SST(&DATA 103 6)) +
               PRTTXT(%SST(&DATA 151 30))
    

    I used the substring function in that example. You can also concatenate. Notice the COMPANY parameter in the following example.

    DCL        VAR(&DATA) TYPE(*CHAR) LEN(1024)
    DCL        VAR(&COMP1) TYPE(*CHAR) LEN(1)
    DCL        VAR(&COMP2) TYPE(*CHAR) LEN(1)
    
    MYCMD      COMPANY(&COMP1 *CAT &COMP2) +
               CUSTOMER(%SST(&DATA 103 6)) +
               PRTTXT(%SST(&DATA 151 30))
    

    5. You may specify limited validation of parameter values in a command definition. For each parameter, you may specify such things as:

    • Valid values: A list of up to 300 constants that define the only permitted values
    • Relational expression: A logical expression that defines a relationship between different parameters
    • Range: Inclusive limits within which the value of a parameter value must fall
    • Full field required: Whether or not the value of the parameter may include trailing blanks

    You may also name a validity checking program in the Create Command (CRTCMD) command. This program runs before the command-processing program, and allows you to define even more stringent parameter validation.

    6. Commands are not afflicted with the default parameter definitions inherent in CALL.

    • Numeric literals are passed as 15-digit packed-decimal values of five decimal places
    • Character literals of 32 bytes or less are passed as 32-byte values
    • Character literals longer than 32 bytes are passed as is

    When it comes to the CMD parameter of the Submit Job (SBMJOB) command, these rules apply to variables as well. Submitting a CALL with parameters to a job queue can be a pain. But submitting a command is no big deal. The command processor straightens everything out.

    7. The command processor provides a nice prompting feature, which you can use from the command line, when editing a source member, and when prompting a command parameter in another command, such as Submit Job (SBMJOB). Because of the prompter, you can do a much better job filling in the parameters properly.

    An Example

    Let’s say you’ve written a wonderful program that’s going to revolutionize the Accounts Receivable department. It’s really more than one program; you’ve created three objects.

    • AR100P: An externally described printer file to define a report
    • AR100R: An RPG program with embedded SQL to select the requested data and create the report
    • AR100C: A CL program to apply print text to the printer file, call the RPG program and handle errors and messaging

    Job well done!

    Your super-duper application requires three values to be supplied at run time.

    • A two-digit company number, indicating which company is to be reported.
    • A six-digit customer number. If this value is positive, the customer assigned that account number will be the only customer on the report. If this value is zero or negative, all customers of the selected company will appear on the report.
    • A 30-character string of text, which will print at the bottom of each page of the report.

    Here are some pieces of the CL program showing the parameter definitions.

    pgm parm(&inCompany &inCustomer &inPrtTxt)
    
    dcl   &inCompany     *dec       2
    dcl   &inCustomer    *dec       6
    dcl   &inPrtTxt      *char     30
    dcl   &Status        *char      8
    
    ovrprtf ar100p prttxt(&inPrtTxt)
    call    ar100r parm(&inCompany &inCustomer &Status)
    dltovr  ar100p
    
    if (%sst(&Status 4 5) *ne '00000') do
       sndpgmmsg  msgid(cpf9898) msgf(qcpfmsg) msgtype(*diag) +
                    msgdta('Program' *bcat &PgmName *bcat +
                           'ended abnormally with status' *bcat &Status)
       goto Escape
    enddo
    

    You’ve been asked to place several invocations of this application–one for each company–on the job scheduler to run overnight throughout the week. There’s no good way to do this using CALL, due to the lengths of the company and customer parameters.

    However, if you’ll define a command to run the CL program, scheduling the job will be easy. Here’s the source for command AR100:

    CMD        PROMPT('Accounts Receivable Report')
    PARM       KWD(COMPANY) TYPE(*DEC) LEN(2 0) REL(*GT 0) +
                 MIN(1) PROMPT('Company')
    PARM       KWD(CUSTOMER) TYPE(*DEC) LEN(6 0) DFT(*ALL) +
                 REL(*GT 0) SPCVAL((*ALL -1)) +
                 PROMPT('Customer')
    PARM       KWD(PRTTXT) TYPE(*CHAR) LEN(30) EXPR(*YES) + 
                 PROMPT('Print text')
    

    Here’s how to create the command:

    CRTCMD CMD(MYLIB/AR100)
           PGM(*LIBL/AR100C)
           SRCFILE(MYLIB/QCMDSRC)
           SRCMBR(AR100)
    

    And here’s how to schedule it to run:

    ADDJOBSCDE
       JOB(AR100_3) 
       CMD(AR100 COMPANY(3) CUSTOMER(*ALL) PRTTXT('Give to Billy Ruben'))
       FRQ(*WEEKLY)
       SCDDAY(*SUN *MON *TUE *WED *THU)
       SCDTIME(230000)
       JOBD(ARJOBD)
    

    In My Experience. . .

    The example in this article includes a command that executes a CL program. I don’t want to give the impression that the command-processing program has to be written in CL. It can be written in any language. However, as I think back on commands I’ve written over the past 25 or so years, the majority of my commands have executed CL programs.

    Also, I don’t want to give the impression that all programs need command interfaces. If a program has few or no parameters, or is called only from other programs, the usual CALL mechanism is adequate. My experience is that only a very small percentage of programs can benefit from a command interface. However, in the case of a program that is called from many CL programs (i.e., a utility), I find that writing a command interface, even if none is needed, enhances readability and facilitates program modification.



                         Post this story to del.icio.us
                   Post this story to Digg
        Post this story to Slashdot

    Share this:

    • Reddit
    • Facebook
    • LinkedIn
    • Twitter
    • Email

    Tags:

    Sponsored by
    Midrange Dynamics North America

    With MDRapid, you can drastically reduce application downtime from hours to minutes. Deploying database changes quickly, even for multi-million and multi-billion record files, MDRapid is easy to integrate into day-to-day operations, allowing change and innovation to be continuous while reducing major business risks.

    Learn more.

    Share this:

    • Reddit
    • Facebook
    • LinkedIn
    • Twitter
    • Email

    Sponsored Links

    Four Hundred Monitor Calendar:  Latest info on national conferences, local events, & Webinars
    looksoftware:  Integrate IBM i apps with web services. FREE Webcast. March 9
    System i Developer:  Upgrade your skills at RPG & DB2 Summit in Orlando, March 22-24

    IT Jungle Store Top Book Picks

    BACK IN STOCK: Easy Steps to Internet Programming for System i: List Price, $49.95

    The iSeries Express Web Implementer's Guide: List Price, $49.95
    The iSeries Pocket Database Guide: List Price, $59
    The iSeries Pocket SQL Guide: List Price, $59
    The iSeries Pocket WebFacing Primer: List Price, $39
    Migrating to WebSphere Express for iSeries: List Price, $49
    Getting Started with WebSphere Express for iSeries: List Price, $49
    The All-Everything Operating System: List Price, $35
    The Best Joomla! Tutorial Ever!: List Price, $19.95

    FIS Sells Missouri Bank and Trust on IBM i Solution New Power Systems VP Talks IBM i Strategy, Roadmaps

    Leave a Reply Cancel reply

Volume 11, Number 6 -- February 16, 2011
THIS ISSUE SPONSORED BY:

SEQUEL Software
WorksRight Software
System i Developer

Table of Contents

  • Commands: Underused and Unappreciated
  • OUTQ vs. PRTDEV
  • Admin Alert: Six Techniques to Prevent Power i Upgrades from Slowing Down

Content archive

  • The Four Hundred
  • Four Hundred Stuff
  • Four Hundred Guru

Recent Posts

  • Meet The Next Gen Of IBMers Helping To Build IBM i
  • Looks Like IBM Is Building A Linux-Like PASE For IBM i After All
  • Will Independent IBM i Clouds Survive PowerVS?
  • Now, IBM Is Jacking Up Hardware Maintenance Prices
  • IBM i PTF Guide, Volume 27, Number 24
  • Big Blue Raises IBM i License Transfer Fees, Other Prices
  • Keep The IBM i Youth Movement Going With More Training, Better Tools
  • Remain Begins Migrating DevOps Tools To VS Code
  • IBM Readies LTO-10 Tape Drives And Libraries
  • IBM i PTF Guide, Volume 27, Number 23

Subscribe

To get news from IT Jungle sent to your inbox every week, subscribe to our newsletter.

Pages

  • About Us
  • Contact
  • Contributors
  • Four Hundred Monitor
  • IBM i PTF Guide
  • Media Kit
  • Subscribe

Search

Copyright © 2025 IT Jungle