Tuesday, August 8, 2023

Convert character to hexadecimal

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:

  1. cvthc:  Convert character to hex
  2. 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.

line 22: Display the result:

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.

2 comments:

  1. Why did it return in Upper Case?

    ReplyDelete
    Replies
    1. On line 18 I use the %UPPER to convert the string to be upper case.

      Delete

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.