Passing Variable Length fields between RPG and CL

Passing Variable Length fields between RPG and CL
Passing Variable Length fields between RPG and CL
Passing Variable Length fields between RPG and CL

RPG IV program or procedures supports the variable length fields(using the VARYING keyword), however ILE CL does not support the variable length fields and this creates an error Length of varying length variable is out of range (C G D F) when we do pass the field lets say length 10 in CL to the 10 length Varying field in RPGLE program/procedure.

For Example

There is one CL program that declares name character variable of length 10 and pass it as a parameter to RPG IV program using CALLPRC and in RPG IV program that NAME variable is defined as variable length character field using VARYING keyword in PR and PI. So this gives error Length of varying length variable is out of range. See the below CL and RPG script that will cause this error.

CL1 program

             PGM                                                     
             DCL        VAR(&NAME) TYPE(*CHAR) LEN(10) VALUE('AMIT') 
             CALLPRC    PRC(RPG1) PARM((&NAME *BYREF *DFT))          
             RETURN                                                  
             ENDPGM                                                  

command used to create CL1 module

CRTCLMOD MODULE(EASYCLASS1/CL1)     
           SRCFILE(EASYCLASS1/JAN2024)
           SRCMBR(CL1)                
           REPLACE(*YES)               
             DBGVIEW(*SOURCE)           

command used to create CL1 program

CRTPGM PGM(EASYCLASS1/CL1) 
         MODULE(EASYCLASS1/CL1 RPG1) 
         ACTGRP(*CALLER)

RPG1 program

     DRPG1             PR                                 
     D  NAME                         10A   CONST VARYING  
                                                          
     DRPG1             PI                                 
     D  NAME                         10A   CONST VARYING  
     Dl_NAME           S             10A   VARYING        
      /free                                               
        l_Name = NAME;                                    
        return;                                           
      /end-free                                           

command used to create RPG1 module

CRTSQLRPGI OBJ(EASYCLASS1/RPG1)        
           SRCFILE(EASYCLASS1/JAN2024) 
           SRCMBR(RPG1)                
           COMMIT(*NONE)               
           OBJTYPE(*MODULE)            
           REPLACE(*YES)               
           DBGVIEW(*SOURCE)            

command used to create RPG1 program

CRTPGM PGM(EASYCLASS1/RPG1) MODULE(EASYCLASS1/RPG1) ACTGRP(*CALLER)

Call program and Error occurred

CALL CL1
                           Display Program Messages                            
                                                                               
 Job 378884/EASYCLASS/QPAD185446 started on 01/29/24 at 19:32:21 in subsystem  
 Length of varying length variable is out of range (C G D F).                  
                                                                               
                                                                               
                                                                               
                                                                               
                                                                               
                                                                               
                                                                               
                                                                               
                                                                               
                                                                               
                                                                               
                                                                               
                                                                               
                                                                               
 Type reply, press Enter.                                                      
   Reply . . .   ___________________________________________________________                                                              
 __________________________________________________________________________                                                                              
                                                                               

Why this issue occurs

The problem here in the above example is that CL program does not support the variable length fields and RPGLE do support variable length fields. So, when we pass a fixed length character field like the &NAME variable in above example rom program CL1 i.e CLLE program to RPGLE program named RPG1 then that RPG1 program/procedure expects a variable field length, the field length attribute is not included and is missing and RPG1 program assumes that the data is corrupted.

Variable Length Fields

Variable length field basically consists of two parts:

  1. an integer field that holds the length(binary value): holds the current length of the field content
  2. followed by the actual data itself

For fields length upto 65535 characters, that integre portion is of two bytes in length and for fields longer than 65535 then that length portion occupies 4 bytes in length. Therefore, it is clear that variable length fields always occupies more bytes than its defined length.

If we consider above example program RPG1 and CL1, then For a varying field length of 10 occupies 12 bytes of storage. Those extra bytes are two byte binary value stored internally as a two byte binary prefix and the field length attribute is hidden by RPG IV because of RPG intergrated support for variable field length. The two byte prefix length is automatically inserted and maintained by the RPG compiler.

Finally, Passing Variable length fields from RPG to RPG/calling proceudre is easy as the compiler itself ensures that the data is formatted properly. However, when we call the RPG procedure from CL, no prototyping involved in that case and one has to manually ensure that the passed variable is properly formatted as per defined in RPG.

CL support for Variable length fields

CL does not have support for the variable field lengths. Therefore, in order to properly pass a variable field length from CL to PRG IV program/procedure we have to manually prefix the 2 byte length (binary) in the field and increasing the length as well. Therefore, if we consider above example, the &NAME field should be increased from length 10 to 12 in CL program and added two bytes to the field length. To achieve this we use %BIN CK built-in function.

Syntax of %BIN CL built-in function

%BIN CL built-in function accepts a field name, a starting position, and a length(number of characters)

%BIN(Character-Field-Name Start-Position Length)

Correctly passing variable length field between CL and RPG

CL2 program

             PGM                                             
             DCL        VAR(&NAME) TYPE(*CHAR) LEN(12)       
             CHGVAR     VAR(%SST(&NAME 3 10)) VALUE('AMIT')  
             CHGVAR     VAR(%BIN(&NAME 1 2)) VALUE(4)        
             CALLPRC    PRC(RPG1) PARM((&NAME *BYREF *DFT))  
             RETURN                                          
             ENDPGM                                           

command used to create CL1 module

CRTCLMOD MODULE(EASYCLASS1/CL2)     
           SRCFILE(EASYCLASS1/JAN2024)
           SRCMBR(CL2)                
           REPLACE(*YES)               
             DBGVIEW(*SOURCE)           

command used to create CL1 program

CRTPGM PGM(EASYCLASS1/CL2) 
         MODULE(EASYCLASS1/CL2 RPG1) 
         ACTGRP(*CALLER)

RPG1 program

     DRPG1             PR                                 
     D  NAME                         10A   CONST VARYING  
                                                          
     DRPG1             PI                                 
     D  NAME                         10A   CONST VARYING  
     Dl_NAME           S             10A   VARYING        
      /free                                               
        l_Name = NAME;                                    
        return;                                           
      /end-free                                           

command used to create RPG1 module

CRTSQLRPGI OBJ(EASYCLASS1/RPG1)        
           SRCFILE(EASYCLASS1/JAN2024) 
           SRCMBR(RPG1)                
           COMMIT(*NONE)               
           OBJTYPE(*MODULE)            
           REPLACE(*YES)               
           DBGVIEW(*SOURCE)            

command used to create RPG1 program

CRTPGM PGM(EASYCLASS1/RPG1) MODULE(EASYCLASS1/RPG1) ACTGRP(*CALLER)

Call program and Success

CALL CL2

This time program will be run fine without any error.

Post a Comment

© AS400 and SQL Tricks. All rights reserved. Developed by Jago Desain