Hear from our iSeries experts. Put in your two cents.
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:
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
| 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 |
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.