• The Four Hundred
  • Subscribe
  • Media Kit
  • Contributors
  • About Us
  • Contact
Menu
  • The Four Hundred
  • Subscribe
  • Media Kit
  • Contributors
  • About Us
  • Contact
  • Guru: The CALL I’ve Been Waiting For

    June 20, 2022 Ted Holt

    Christmas came to my house early this year. May 3, to be exact. Boy! Was Santa Claus good to me! IBM gave me two presents! The first was a CL enhancement that I had desired for years. The second was an improvement that, to my delight, almost obsoletes a utility I wrote years ago. Both have to do with the CL CALL command.

    CALL is arguably the most used and most important command in CL, yet for all these years it has remained untouched. I’m glad that IBM has seen fit to devote time and resources to the enhancement of this important language, and especially glad to see the enhancement of CALL.

    Present #1: Expressions

    Let’s begin with the present I was hoping for.

    Assume a CL program that receives two parameters — a qualified object name and an object type. The qualified object name is a 20-byte character value. The first 10 characters are the object name, and the second 10 characters are a library name or a special value, such as *LIBL.

    If we want to make sure the object exists, we can do it this way.

    pgm  parm(&inQualObj &inObjType)
    
       dcl   &inQualObj    *char     20
       dcl   &inObjType    *char     10
    
       ChkObj  obj(%SST(&inQualObj 11 10)/%SST(&inQualObj 1 10)) +
                  ObjType(&inObjType) aut(*ObjExist)
    

    Notice the substring functions in the OBJ parameter. Two of them! The OBJ parameter allows expressions (a good idea, in my opinion), so I don’t have to copy the object name and library name into scratch variables.

    Suppose we want to pass the library name to another program. For most of the history of IBM i and its predecessors, we had to declare a single-use variable, like this:

    pgm  parm(&inQualObj &inObjType)
    
       dcl   &inQualObj    *char     20
       dcl   &inObjType    *char     10
       dcl   &Lib          *char     10
    
       ChgVar   &Lib   %SST(&inQualObj 11 10)
       call  pgm(X)  parm(&Lib)
    

    Why? Because we weren’t allowed to use expressions in the PARM parameter of the CALL command. This has annoyed me for a long time.

    Later, IBM introduced defined variables, which I consider an improvement.

    pgm  parm(&inQualObj &inObjType)
    
       dcl   &inQualObj    *char     20
       dcl   &inObjType    *char     10
       dcl   &Lib          *char     10 stg(*defined) DefVar(&inQualObj 11)
    
       call  pgm(X)  parm(&Lib)
    

    There’s no need for the CHGVAR command because &Lib overlays &inQualObj in memory. Changing one changes the other.

    But now, at last, we can use expressions in the PARM parameter!

    pgm  parm(&inQualObj &inObjType)
    
       dcl   &inQualObj    *char     20
       dcl   &inObjType    *char     10
    
       call  pgm(X)  parm(%SST(&inQualObj 11 10))
    

    Just think, no more having to declare single-use variables just to pass a parameter to a program. Fabulous!

    Here’s an example that uses a logical value.

    A CL program receives a four-byte character value of *YES or *NO to indicate whether the job should create a logging file or not. It needs to convert this value to ‘1’ or ‘0’ when passing it along to another program. Here’s how we’ve had to do that until now.

    pgm   parm(&CrtLog)
    
       dcl   &CrtLog      *char      4
       dcl   &CrtLogLgl   *lgl
    
       chgvar   &CrtLogLgl   (%upper(&CrtLog) *eq *YES)
    
       call     pgm(X)  PARM(&CrtLogLgl)
    

    Here’s the new way.

    pgm   parm(&CrtLog)
    
       dcl   &CrtLog  *char      4
    
       call  pgm(X)  PARM(((%upper(&CRTLOG) *EQ *YES) (*LGL 1)))
    

    Here’s an example with concatenation.

    call  pgm(x)   (%sst(&ItemType 5 1) *cat %sst(&Option 2 1))
    

    And so it goes. I haven’t tested this exhaustively yet, but it seems safe to assume that anything you can put into the VALUE parameter of the CHGVAR command can be used in PARM.

    Gift #2: Parameter Definitions

    To understand just how wonderful the second present from IBM is, let’s first be sure we understand how CL has worked since its introduction to the world.

    The people who created CL for the System/38 those many eons ago had to make some decisions. One question they faced concerned the use of literal parameters in the CALL command, namely, how such parameters should be stored in memory. They adopted a convention, which has been written about many times. (Here’s one.)

    • Character literals of 32 bytes or less are stored in 32 bytes of memory. If the literal is less than 32 bytes long, the system pads it with trailing blanks.
    • Character literals of more than 32 bytes are stored in the number of bytes needed to contain all characters up to and including the last non-blank character. To put it another way, trailing blanks are not stored in memory.
    • Numeric literals are passed as 15-digit packed-decimal numbers with five assumed decimal positions.

    Programmers have had to work around these limitations. Some common methods include:

    • Define all parameters as character in the called program.
    • Append an extra non-blank character to a character literal.
    • Pass data to a program through the local data area rather than through parameters.
    • Declare numeric parameters as 15,5 in the called program.
    • Pass numeric values as hexadecimal literals.
    • Create a command interface for the called program.

    Well, not any more. Now we can tell the system how we want a literal value to be stored.

    In this example, the literal 302 is passed to program X as a five-digit packed-decimal value.

    CALL PGM(X) PARM((302 (*DEC 5 0)))
    

    Bear in mind that the system may see literal values where we use variables. The system knows about variable definitions within a CL program/procedure. Otherwise, the CALL is interpreted. A good example is the Submit Job (SBMJOB) command.

    dcl   &CusNbr  *dec       5
    
    SbmJob   cmd(CALL PGM(X) PARM((&CUSNBR))) job(Whatever)
    

    The Submit Job command creates a request message, which the new job will receive and execute as a command. The new job will not know that &CusNbr was defined as five digits packed in the submitting program. Instead, it will treat the customer account number as if were defined as 15,5. If program X defines the customer number parameter as 5,0 packed, the program will abend with a data decimal error.

    Instead, this program needs to pass the customer number to program X as a five-digit packed-decimal number. Here’s how it’s done.

    dcl   &CusNbr  *dec       5
    
    SbmJob   cmd(CALL PGM(X) PARM((&CUSNBR (*DEC 5 0)))) + 
                job(Whatever)       
    

    Suppose that program X defines the customer number as a seven-digit packed-decimal number. We can reformat the number appropriately.

    dcl   &CusNbr  *dec       5
    
    SbmJob   cmd(CALL PGM(X) PARM((&CUSNBR (*DEC 7 0)))) + 
                job(Whatever)       
    

    This new enhancement almost obsoletes a utility I wrote years ago and have been using since. I refer to my RUN command. It seems that I end up installing this utility on every system I work on. Maybe I’ll need it less often from now on.

    The reason I say that this new CALL behavior almost obsoletes RUN is that I ran into one instance where CALL wouldn’t do what needed to be done. Here’s a command from the article I linked to in the previous paragraph.

    RUN PGM(MYPGM) PARM(('I like cheese a whole lot!' *CHAR (64)) +
                        (3.14 *DEC (7 2)) +
                        (12345678901 *DEC (11)))
    

    I converted this code to a CALL.

    call  pgm(MYPGM)  PARM(('I like cheese a whole lot!' (*CHAR 64)) +
                           (3.14 (*DEC 7 2)) +
                           (12345678901 (*DEC 11 0)))
    

    Guess what? It doesn’t compile. The compiler allows me to define the third parameter with 11 significant digits, but it won’t let me pass an 11-digit literal. It appears I won’t completely retire RUN just yet, but maybe I won’t have to use it as often as before.

    Einstein Is My Model

    Albert Einstein said, “Everything should be made as simple as possible, but not simpler.” I subscribe to the same philosophy. I write complicated source code when I have to, but only when nothing simpler will serve the purpose.

    I’ve received the CALL I had been waiting for. Thanks to these new enhancements, my CL programs and procedures will be less cluttered with single-use variables and, I hope, easier to read and work on.

    RELATED STORIES

    Value An Expression? *YES!

    Guru: Passing Parameters From The Command Line

    The RUN Utility: Call a Program with Correctly Formatted Parameters

    Everything should be made as simple as possible, but not simpler.

    Albert Einstein Quotes About Simplicity

    Share this:

    • Reddit
    • Facebook
    • LinkedIn
    • Twitter
    • Email

    Tags: Tags: 400guru, CALL, CL, FHG, Four Hundred Guru, IBM i, System/38

    Sponsored by
    Raz-Lee Security

    Start your Road to Zero Trust!

    Firewall Network security, controlling Exit Points, Open DB’s and SSH. Rule Wizards and graphical BI.

    Request Demo

    Share this:

    • Reddit
    • Facebook
    • LinkedIn
    • Twitter
    • Email

    A Frank Solstice What Is Code Transformation Even?

    7 thoughts on “Guru: The CALL I’ve Been Waiting For”

    • Jay says:
      June 20, 2022 at 9:08 am

      What PTF(s) for what OS version(s), adds these wonderful new features?

      Reply
    • Doug says:
      June 20, 2022 at 10:51 am

      Well, I’m feeling a bit ignorant…
      I have never seen this syntax in CL before: %(&CrtLog), or, %(&ItemType 5 1)

      What coolness does %(varname) do?

      (Or are these just typos?)

      Reply
    • Glenn Gundermann says:
      June 20, 2022 at 11:19 am

      What in fact does the % do in this statement?
      chgvar &CrtLogLgl (%(&CrtLog) *eq *YES)

      Reply
    • TED HOLT says:
      June 20, 2022 at 11:56 pm

      Sorry, folks. We had a weird, unexplainable production problem. Somehow %upper and %sst became a single % in some of the figures. They have been corrected.

      Reply
    • Tommy Christopherson says:
      July 1, 2022 at 1:32 pm

      I’ve tried the parameter definition in passing to an RPG program but I get a “List or expression not valid for parameter PARM”.
      Here’s my attempt:

      call pgm(apgm01) parm((‘This field is 55’ (*CHAR 55)) (9999999.99 *DEC (9
      2)) (‘This field is 100 long’ (*CHAR 100)) (12 *DEC (2 0)))

      RPG Program:
      **FREE
      Ctl-Opt Copyright(‘(c) 2021 City of Euless, Texas’)
      DFTACTGRP(*NO) ACTGRP(*CALLER) Usrprf(*Owner) Aut(*Exclude)
      Option(*srcstmt : *nodebugio) Debug(*DUMP)
      AlwNull(*UsrCtl) PgmInfo(*PCML : *MODULE) DatFmt(*USA);

      Dcl-PI APGM01;
      Field1 Char(55);
      Number1 Packed(9:2);
      Field2 Char(100);
      Number2 Zoned(2:0);
      End-PI;

      Dcl-S AllFields Char(200);

      AllFields = %Trim(Field1) + %Trim(%EditC(Number1 : ‘J’)) +
      %Trim(Field2) + %Trim(%EditC(Number2 : ‘Z’));

      *InLR = *On;

      Our box is on 7.4 and has the latest Cume and Technology Refresh

      Reply
    • JT says:
      July 21, 2022 at 10:24 am

      What PTF(s) for what OS version(s), adds these wonderful new features?

      Reply
    • Sean Wayman says:
      December 22, 2022 at 2:20 am

      Nice new feature. Unfortunately my shop is 7.3 and won’t be upgrading any time soon. I did want to try you RUN solution but the link to the code seems to be broken.

      Reply

    Leave a Reply Cancel reply

TFH Volume: 32 Issue: 43

This Issue Sponsored By

  • ARCAD Software
  • Profound Logic
  • New Generation Software
  • LaserVault
  • Raz-Lee Security

Table of Contents

  • Plotting A Middle Age Career Change To IBM i
  • What Is Code Transformation Even?
  • Guru: The CALL I’ve Been Waiting For
  • A Frank Solstice
  • The Inevitable Wave Of Power9 Withdrawals Begins

Content archive

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

Recent Posts

  • Liam Allan Shares What’s Coming Next With Code For IBM i
  • From Stable To Scalable: Visual LANSA 16 Powers IBM i Growth – Launching July 8
  • VS Code Will Be The Heart Of The Modern IBM i Platform
  • The AS/400: A 37-Year-Old Dog That Loves To Learn New Tricks
  • IBM i PTF Guide, Volume 27, Number 25
  • 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

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