Wednesday, January 21, 2026

RPG BiFs that now convert CCSID

As the computing world has become more "open" we need to process data that comes in different character sets, not just the EBCDIC CCSID in the IBM i partitions we are working on. Modern RPG has been able to handle all of the character sets, with various Built in Functions, BiF, to convert the character set from one to another.

The RPG PTFs that accompanied new Technology Refreshes, IBM i 7.6 TR1 and IBM i 7.5 TR7, included an improvement to character handling. Some BiFs will now automatically match the character types of the data in the variables used. This post is going to explain what they are, and any errors I found.

The BiFs that do this implicit CCSID conversion are:

Command Mapping rule
%CHECK(valid_values : source) valid_values converted to the type and CCSID of source
%CHECKR(valid_values : source) valid_values converted to the type and CCSID of source
%LOOKUP(search_argument : array) search_argument converted to the type and CCSID of the array
%SCAN(search_argument : source) search_argument converted to the type and CCSID of source
%SCANR(search_argument : source) search_argument converted to the type and CCSID of source
%SCANRPL(from_string : to_string : source) from_string and to_string converted to the type and CCSID source
%SPLIT(source : split_characters) split_characters converted to the type and CCSID of the source
%TLOOKUP(search_argument : table) search_argument converted to the type and CCSID of the table
%TRIMx(source : trim_characters) trim_characters converted to the type and CCSID of the source
%XLATE(from_characters : to_characters : source) from_characters and to_characters converted to the type and CCSID of the source

I am not going to show examples of all of the above, I have picked two of the ones I use many times to demonstrate this functionality.

For a while we have been able to define a variable in a RPG program that contains data that is not the same character set that the program is using:

01  dcl-s Work1 char(10) ccsid(1208) ;
02  dcl-s Work2 ucs2(10) ;

Line 1: Defining this variable with the CCSID of 1208, which is UTF-8.

Line 2: This variable is defined as UCS-2. Notice that I do not define the variable as character, I define it as the data type UCS2.

When I look in compile listing I can see the character sets used:

Global Field References:
     Field             Attributes
     WORK1             A(10)
                       CCSID(1208)
     WORK2             C(10)
                       CCSID(13488)

In my first example I am going to use the %SCAN BiF. This first example program was written and compiled on a partition that does not have the latest RPG PTFs. Therefore, this can be said to be the example of the "before" situation:

01  **free
02  dcl-s String1 ucs2(10) inz('GOURD') ;
03  dcl-s Comparison char(1) inz('O') ;
04  dcl-s Position uns(3) ;

05  Position = %scan(Comparison : String1) ;
06  dsply ('1 = ' + %char(Position)) ;

07  Position = %scan(%ucs2(Comparison) : String1) ;
08  dsply ('2 = ' + %char(Position)) ;

09  Position = %scan(Comparison  : %char(String1) ) ;
10  dsply ('3 = ' + %char(Position)) ;

11  *inlr = *on ;

Line 2: The variable contains the string that will be scanned, it is defined with the data type UCS-2.

Line 3: This variable contains the character that will be scanned for.

Line 4: I need a variable to contain the number of the place within the scanned string the scan character is found.

Line 5: This is the scan statement that will test if either of the variables used will have their character type changed.

Line 6: Display where in the string the scanned for character is found.

Line 7: If the automatic character conversion does not happen I would need to convert one of the two variables to be the same character set as the other. Here I am converting the scanned for character value to UCS-2, using the %UCS2 BiF, to match the data type in the variable String1, UCS-2.

Line 9: Convert the data in variable String1, so it match the contents of the Comparison.

When I compile the program I get the following error:

 Msg id  Sv   Statement  Message text
*RNF0353 20      000500  The first and second parameters of %SCAN or %SCANR are not
                         of the same type.

Which tells me I cannot use the default CCSID character, 37 = US English, with the UCS-2. If I comment out line 5 and 6, the program successfully compiles and executes without error.

The next program was created on a partition with the necessary PTFs:

01  **free
02  dcl-s String1 ucs2(10) inz('GOURD') ;
03  dcl-s String2 char(10) ccsid(1208) inz('LEMON') ;
04  dcl-s String3 char(10) ccsid(273) inz('ORANGE') ;
05  dcl-s Comparison char(1) inz('O') ;
06  dcl-s Position uns(3) ;

07  Position = %scan(Comparison : String1) ;
08  dsply ('1 = ' + %char(Position)) ;

09  Position = %scan(Comparison : String2) ;
10  dsply ('2 = ' + %char(Position)) ;

11  Position = %scan(Comparison : String3) ;
12  dsply ('3 = ' + %char(Position)) ;

13  *inlr = *on ;

Lines 2 - 6: These are the variable definitions. This has three variables with different character sets:

  • String1, line 2, is UCS-2
  • String2, line 3, is UTF-8
  • String3, line 4, is the CCSID encoding for use with Austrian and German

Line 7: Here I am comparing the comparison character, which is in the program's default CCSID 37 to the string in the UCS-2 variable.

Line 9: Doing the scan for the comparison character and the string in the UTF-8 variable.

Line 11: Finally, comparing the comparison character to the string in the CCSID 237 variable.

Program compiled without error, and when called displayed the following:

DSPLY  1 = 2
DSPLY  2 = 4
DSPLY  3 = 1

My next program uses the Trim BiF, %TRIM to remove the asterisks ( * ) in a string. The same source code was used on both the non-current PTFs and current PTFs partitions:

01  **free
02  dcl-s String1 ucs2(10) inz('***APPLE**') ;
03  dcl-s String2 char(10) ;
04  dcl-s TrimChar char(1) inz('*') ;

05  String2 = %trim(String1 : TrimChar) ;

06  String2 = %trim(%char(String1) : TrimChar) ;

07  dsply String2 ;

08  *inlr = *on ;

Line 2: I have defined the variable that needs to have the asterisks trimmed as UCS-2.

Line 3: This variable will contain the results of the "trimming".

Line 4: The character to be "trimmed", removed from the string. It is in the default CCSID, 37.

Line 5: If the character conversion can happen this line should not cause an error.

Line 6: Here is a variation of the above line, which converts the variable that contains the string to character, using the %CHAR BiF. This will convert it from UCS-2 to CCSID 37.

When this source was compiled in the partition that does not have the relevant PTFs, the following compile error happened:

 Msg id  Sv   Statement  Message text
*RNF0374 20      000600  The second parameter TRIMCHAR for %TRIM is not valid;
                         parameter is ignored.

When I commented out line 5 the program compiled, and executed without error.

When I compiled the source code in the partition that has the latest RPG PTFs I received the following error:

Compilation stopped. Internal failure occurred. Error code is  1.

I have never seen this error before. When I prompted the error the following detail was displayed:

                      Additional Message Information
Message ID . . . . . . :  RNS9311      Severity . . . . . . . :  50
Message type . . . . . :  Information
Date sent  . . . . . . :  DD/DD/DD     Time sent  . . . . . . :  TT:TT:TT

Message . . . . :   Compilation stopped. Internal failure occurred. Error 
  code is  1.
Cause . . . . . :   The possible error codes are:
    1  - Failure occurred in the compiler front end.

When I commented out line 5 the program would compile and execute without error.

I went ahead and tested all of the BiFs I have in the table above, with the exception of %TLOOKUP, and this is what I found:

BiF Compiled containing...
UCS-2 CCSID
%CHECK Yes No
%CHECKR Yes No
%LOOKUP Yes Yes
%SCAN Yes Yes
%SCANR Yes Yes
%SCANRPL Yes Yes
%SPLIT Yes Yes
%TRIMx Yes No
%XLATE Yes Yes

I am hoping a future RPG PTF will allow the BIFs that do not allow CCSID character conversion to do so.

 

You can learn more about the this from the IBM website here.

 

This article was written for IBM i 7.6 TR1 and 7.5 TR7.

No comments:

Post a Comment

To prevent "comment spam" all comments are moderated.
Learn about this website's comments policy here.

Some people have reported that they cannot post a comment using certain computers and browsers. If this is you feel free to use the Contact Form to send me the comment and I will post it for you, please include the title of the post so I know which one to post the comment to.