The idea for this post came from a question I was asked by a friend. In a RPG program is there a simple way to convert a character value to hexadecimal, and vice versa.
I know of two Machine Instruction procedures that will do this for me:
- cvthc: Convert character to hex
- cvtch: Convert hex to character
In my examples I am going to convert a couple of character strings to hex, and then convert one back from hex to character. All of this I performed in one RPG program. Let me start by showing all the definitions:
01 **free 02 ctl-opt dftactgrp(*no) ; 03 dcl-pr CharToHex extproc('cvthc') ; //Convert char to hex 04 *n char(2048) options(*varsize) ; // Hex out 05 *n char(1024) options(*varsize) ; // Char in 06 *n int(10) value ; // Length 07 end-pr ; 08 dcl-pr HextoChar extproc('cvtch') ; //Convert hex to char 09 *n char(1024) options(*varsize) ; // Char out 10 *n char(2048) options(*varsize) ; // Hex in 11 *n int(10) value ; // Length 12 end-pr ; 13 dcl-s CharVar char(50) ; 14 dcl-s HexVar char(100) ; |
Line 1: I always wrote all new code in totally free RPG. You should be doing the same.
Line 2: As I am calling external procedures I cannot execute this program in the default activation group. In the control options I tell the program not to use the default activation group.
Lines 3 – 7: The Procedure Prototype for the external procedure to convert character to hex.
Line 3: I have decided not to use the external procedure's name, cvthc, and have given it what I consider more explanatory name: CharToHex. As I have not used the external procedure's name I have to give it in the EXTPROC keyword.
Lines 4 – 6: Regular readers know that I never give the procedure prototype's parameters names. Therefore, I always give them a name of null, *N. Why bother give them names if I am not going to use that name when the procedure is called?
Line 4: The first parameter is the hex text returned by the procedure, it has to be twice the size as the character parameter. This is because when a character is translated to hex the hex value is two long.
Line 5: The parameter that will contain the character string.
I have found that the two parameters do not have to be a particular length. I chose the sizes I used thinking there would probably never be a scenario where I would have a string to exceed the lengths given.
Line 6: The length for the returned string.
Lines 8 – 12: Procedure prototype for the external procedure that converts hex to character, cvtch. I have called it HexToChar. The only difference is that the character and hex parameters are reversed, with character parameter coming first and the hex parameter comes second.
Lines 13 and 14: Defining variables for the character and hex strings.
And onto first conversion:
15 CharVar = 'Simon was here' ; 16 CharToHex(HexVar : CharVar : %len(HexVar)) ; 17 dsply ('1: ' + %subst(HexVar: 1 : 45)) ; |
Line 15: Moving the character string into the character variable.
Line 16: The external procedure call. The length need to be the length of the hex parameter. I have calculated the length value using the Length Built in Function, %LEN.
Line 17: I am using the Display operation code, DSPLY, to show the contents of the hex variable. The DSPLY is limited to returning 52 characters. As HexVar is 100 characters, and there is a prefix, I can only use the first 45 characters in the variable.
The result is:
DSPLY 1: E28994969540A681A2408885998540404040404040404 |
The "40" at the end of the string is the hex for space.
The next example is to show that the upper case version of the character string returns a different string.
18 CharVar = %upper(CharVar) ; 19 CharToHex(HexVar : CharVar : %len(HexVar)) ; 20 dsply ('2: ' + %subst(HexVar: 1 : 45)) ; |
Line 18: Convert the character string from lower to upper using the Upper BiF, %UPPER.
Line 19: Call to the external procedure.
Line 20: Display the result, which is different from the first example.
DSPLY 2: E2C9D4D6D540E6C1E240C8C5D9C540404040404040404 |
Last example is taking the hex string generated in the previous code snippet and convert it back to character.
21 HexToChar(CharVar : HexVar : %len(CharVar)) ; 22 dsply ('3: ' + %subst(CharVar : 1 : 45)) ; |
Line 21: Call the convert to hex to character external procedure, cvtch, which I have called HexToChar. With this procedure the length needs to be the length of the character variable.
DSPLY 3: SIMON WAS HERE |
As you have seen using these external procedures is simple and straightforward. Having tried these example my friend immediately incorporated the procedures in their code.
You can learn more about this from the IBM website:
This article was written for IBM i 7.5, and should work for some earlier releases too.
Why did it return in Upper Case?
ReplyDeleteOn line 18 I use the %UPPER to convert the string to be upper case.
Delete