Start of change

Use defined variables

Defined variables make it easy to manage complex data structures in CL by eliminating the need to substring values out of a large variable.

Defined variables can be used to map different parts of the defined on variable or the same part of a given variable in different ways.

In the following example, the variables &LIBNAME will always be equal to the first 10 bytes of &OBJECT. Using the defined variable &LIBNAME will improves the readability of the code and makes it easier to work with. The variable &OBJECT provides the storage for the &LIBNAME and &OBJNAME variables.

PGM
DCL &OBJECT  *CHAR 20
DCL &LIBNAME *CHAR 10 STG(*DEFINED) DEFVAR(&OBJECT)
DCL &OBJNAME *CHAR 10 STG(*DEFINED) DEFVAR(&OBJECT 11)
:
IF COND(%SST(&OBJECT 11 10) *EQ &OBJNAME) +
   THEN(...))
:
ENDPGM

You can also make the same storage with multiple definitions. In this example, the variables &BINLEN and &CHARLEN both refer to the same 4 bytes of variable &STRUCT. The program can then use the definition that best suits its requirements.

PGM
DCL &STRUCT  *CHAR 50
DCL &BINLEN  *INT   4 STG(*DEFINED) DEFVAR(&STRUCT)
DCL &CHARLEN *CHAR  4 STG(*DEFINED) DEFVAR(&STRUCT)
:
ENDPGM

This example shows how a defined variable can be used to change values in a variable. This example also makes use of the %OFFSET built-in function and a based variable to navigate the library list. This is not the optimal way to do message substation but illustrates some of the capabilities of defined variables.

PGM
DCL &MESSAGE  *CHAR  25 VALUE('LIBRARY NNN IS XXXXXXXXXX')
DCL &SEQUENCE *CHAR   3 STG(*DEFINED) DEFVAR(&MESSAGE  9) 
DCL &MSGLIBN  *CHAR  10 STG(*DEFINED) DEFVAR(&MESSAGE 16) 
DCL &COUNTER  *INT    2                                   
DCL &LIBL     *CHAR 165                                   
DCL &PTR      *PTR      ADDRESS(&LIBL)                    
DCL &LIBLNAME *CHAR  10 STG(*BASED) BASPTR(&PTR)          
:
RTVJOBA SYSLIBL(&LIBL)   
CHGVAR &COUNTER 0        
DOFOR &COUNTER FROM(1) TO(15)                 
   IF (&LIBLNAME *EQ '          ') THEN(LEAVE)
   CHGVAR &SEQUENCE &COUNTER                  
   CHGVAR &MSGLIBN &LIBLNAME                  
   SNDPGMMSG  MSGID(CPF9898) MSGF(QSYS/QCPFMSG) MSGDTA(&MESSAGE)
   CHGVAR %OFS(&PTR) (%OFS(&PTR) + 11)        
ENDDO                                         
:
ENDPGM
End of change