iSpeak

Hear from our iSeries experts. Put in your two cents.

April 20, 2005

Pointers in CL?

At the spring COMMON conference, I had the priveledge to meet Guy Vig, or as he was introduced to me, "Mr. CL". He and I had a conversation about the future of the CL programming language.

Out of the blue, IBM made some profound changes to the CL language in V5R3. In fact, not since ILE support was introduced in V3R1 has CL had such significant changes made to it.

The next release of OS/400 (the one that follows V5R3) promises to continue to offer CL improvements. The proposed changes include support for pointers and defined-on variables that work like data structures.

You may be saying to yourself "Why would I want to use pointers in CL?" or even "Pointers! That's a bad idea! Leave the complicated stuff for C programmers!" At first, I agreed with that sentiment. However, as I thought about it a little more, I warmed up to the idea.

To understand why I think CL could use pointer and based-on variable support, let me explain what I feel the purpose and goal of the CL language is.

The name "CL" stands for "Control Language" and also explains it's purpose. It's purpose is to control the flow of a job, and there are certain things that are important for doing that:

  • The CALL and CALLPRC commands. These are absolutely vital for a control language, since that's what controlling the flow of a job is all about, calling programs.
  • The IF and ELSE commands, and support for variables. Again, part of being in control of the flow of a job means being able to perform some rudamentary calculations and use the results as conditions for whether or not a call should be made.
  • Loops and GOTOs. I could argue that the GOTO command is not needed in any language today, but until V5R3 this was the only way in CL to perform a loop. The ability to loop is absolutely vital to controlling the flow of a job.

Finally, my point: For the ability to call programs, call them conditionally, and loop between them to be effective, you need to be able to pass data between them. In order for CL to be able to pass data correctly, it needs support for the various data types that are available in the high-level languages (HLLs) that it calls! HLLs have support for passing pointers as parameters, and therefore CL should be able to receive those parameters!

Just think if CL didn't have support for the *CHAR (character) data type! How would an RPG program set a variable that could be passed to a different program later? Likewise, a CL program has the ability to read a *DEC (packed decimal) from one program and pass it to another. It should have the same support for pointers and data structures!

The following code is a sample program intended to show off the power of these enhancements. It does something that you couldn't easily do in previous versions of CL -- it reads the contents of a directory in the IFS. For each tab-delimited file that it finds in the directory, it uses CPYFRMSTMF to convert it to a PF that will be later processed by an RPG program:

PGM

     DCL VAR(&NUL)     TYPE(*CHAR) LEN(1)   VALUE(x'00')
     DCL VAR(&DIRNAME) TYPE(*CHAR) LEN(200)
     DCL VAR(&EXT)     TYPE(*CHAR) LEN(4)
     DCL VAR(&POS)     TYPE(*INT)  LEN(4)
     DCL VAR(&SUCCESS) TYPE(*INT)  LEN(4)
     DCL VAR(&HANDLE)  TYPE(*PTR)
     DCL VAR(&ENTRY)   TYPE(*PTR)
     DCL VAR(&NULLPTR) TYPE(*PTR)
     DCL VAR(&STMF)    TYPE(*CHAR) LEN(640)

     /**********************************************************/
     /*  This works like a data structure  It's 796 chars      */
     /*   long with a field called &NAMELEN in positions 53-56 */
     /*   and a field called &NAME in positions 57-640         */
     /**********************************************************/

     DCL VAR(&DIRENT)  TYPE(*CHAR) LEN(796) +
                       STG(*BASED) BASPTR(&ENTRY)
     DCL VAR(&NAMELEN) STG(*DEFINED) DEFVAR(&DIRENT 53) +
                       TYPE(*UINT) LEN(4)
     DCL VAR(&NAME)    STG(*DEFINED) DEFVAR(&DIRENT 57) +
                       TYPE(*CHAR) LEN(640)


     /**********************************************/
     /* Open the /edi/incoming/custdata directory: */
     /* the API returns a NULL pointer to indicate */
     /* failure.                                   */
     /**********************************************/

     CHGVAR VAR(&DIRNAME) VALUE('/edi/incoming/tabdata' *CAT &NUL)

     CALLPRC PRC('opendir') PARM((&DIRNAME)) RTNVAL(&HANDLE)
     IF (&HANDLE *EQ &NULLPTR) DO
        SNDPGMMSG  MSGID(CPF9897) MSGF(QCPFMSG) MSGDTA('Unable +
                  to open directory!') MSGTYPE(*ESCAPE)
     ENDDO


     /**********************************************/
     /* Read the contents of the directory, and    */
     /*  convert each stream file that ends with   */
     /*  '.TAB' to records in a physical file:     */
     /**********************************************/

     CALLPRC PRC('readdir') PARM((&HANDLE *BYVAL)) +
                            RTNVAL(&ENTRY)

     DOWHILE COND(&ENTRY *NE &NULLPTR)

        CHGVAR VAR(&STMF) VALUE(%SST(&NAME 1 &NAMELEN))

        /* extract the last 4 characters from the filename */

        IF (&NAMELEN *GE 4) DO
           CHGVAR VAR(&POS)  VALUE(&NAMELEN - 3)
           CHGVAR VAR(&EXT)  VALUE(%SST(&STMF &POS 4))
        ENDDO
        ELSE DO
           CHGVAR VAR(&EXT)  VALUE('    ')
        ENDDO

        /* if the last 4 are '.TAB' add to our PF, and  +
           delete the original so that it doesn't get   +
           processed again                             */

        IF ((&EXT *EQ '.TAB') *OR (&EXT *EQ '.tab')) DO
            CPYFRMIMPF FROMSTMF(&STMF) TOFILE(TRANMAST) +
                       MBROPT(*ADD) RCDDLM(*CRLF) FLDDLM(*TAB) +
                       RPLNULLVAL(*FLDDFT)
            DEL OBJLNK(&STMF)
        ENDDO

        CALLPRC PRC('readdir') PARM((&HANDLE *BYVAL)) +
                               RTNVAL(&ENTRY)
     ENDDO


     /**********************************************/
     /*  Close the directory                       */
     /**********************************************/

     CALLPRC PRC('closedir') PARM((&HANDLE *BYVAL)) +
                             RTNVAL(&SUCCESS)


     /**********************************************/
     /*  Call an RPG program to process the new    */
     /*  transactions                              */
     /**********************************************/

     CALL PGM(PROCESS)

ENDPGM

The IFS APIs are just one example. There are many useful APIs that become accessible with pointer support! Other examples include string handling functions and database reading/writing/updating. The only thing preventing you from doing this in CL in V5R3 is that there's no pointer data type.

Do you have an opinion of whether pointers or other features are right for CL? If so, please post your comments as a reply to this blog entry.

Posted by at April 20, 2005 12:15 AM

Comments

I've always been of the opinion that a Control Language should be (within limits) as simple as possible - it's all about controlling jobs and working with objects, with the hard work typically being done by other HLL programs.

Are pointers a 'bad' thing? No. But are there better things to be doing with CL? YES!!! (like better file support, which was improved recently but is still FAR from perfect).

Besides, you can pass a pointer 'through' an intermediary CL program by passing it to the CL program as a 16-byte character variable. As long as you don't do anything with the variable, you can then pass it to another program/procedure, which can define it as a pointer...

Posted by: Rory Hewitt at April 21, 2005 11:46 AM

I'm excited by the new features in CL. In addition to pointers, the BY VALUE functionality opens up all kinds of APIs that were not usable from CL, as you've pointed out to me before.

One area I wish were there - maybe it will be - is to declare parameters as BY VALUE. I seem to remember talking to Guy about this but don't remember what the status of this is.

Posted by: Vern Hamberg at April 28, 2005 6:08 AM

Any and All improvements to CL are welcomed. Enhanced DB2 functions (Read/Write/Update/Delete/Insert/RePosition/by Key or RRN) With multiple files per program. The enhancements given in v5r3 are great but just a start. I hope that "Mr CL" - Guy Vig keeps it coming.

Posted by: Paul Dunn at April 28, 2005 2:19 PM

send me some good code's based on date conversion and adding a physical file in DATA AREA and some excellent faqs in C.L

Posted by: abhishek at May 4, 2005 3:23 AM

October 2008
Sun Mon Tue Wed Thu Fri Sat
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31  

Blog Policy

We welcome your comments and opinions and encourage lively debate on the issues. However, Penton Media reserves the right to delete or move any content that it may determine, in its sole discretion, violates or may violate its Terms of Use or is otherwise unacceptable. For more information, see Penton Media's Terms of Use.

ProVIP Sponsors