It’s time to move MOVE out of old RPG Programs
One of the biggest mistakes I’ve made while trying to modernise old RPG code, is simply importing the old code and trying to take the whole thing as one lump upgrade to modern RPG ILE.
Hindsight is 2020, and something I’ve learned from the many code modernization exercises I’ve taken is that it’s much easier to approach your modernization in a modular design. As the old saying goes – What is the easiest way to eat an elephant? It’s one bite at a time!
One of the first things I do when modernising old RPG code is to look through the op codes to replace out anything that has a modern equivalent.
The old RPG MOVE and MOVE LEFT opcodes are prime candidates for this.
MOVE and MOVEL were replaced by the evaluate (EVAL) opcode over a decade ago!
The EVAL opcode gives us many built-in functions a long list of features that are growing every year. By using built in functions like %CHAR and %EDITC we can easily upgrade old RPG code snippets prior to attempting to upgrade the entire program.
Trust me — taking time for this small step will make your modernization effort 20 times easier!!
Why is move bad?
One of the main problems with MOVE and MOVEL is their ability to move numeric data into an alphanumeric storage area and vice versa (a common cause for decimal data error)
So let’s discuss an easy way of handling numeric data with eval and the built in function %char.
This built in function can be used to convert the data value from numeric or date order stamp data into character. Simply put, it will take some data and return it to the program as a pure alphanumeric string. For example, the date 250667 would be returned as ’250667’ or the 10 digit number 0000521.67 would be returned as quote ‘ 521.67’
%CHAR has several components:
%CHAR(expression{: format | ccsid})
%CHAR converts the value of the expression from character, graphic, UCS-2, numeric, date, time or timestamp data to type character.
%CHAR Examples with Date, Time, and Timestamp parameters
DCL-S date DATE INZ(D'1997/02/03');
DCL-S time TIME INZ(T'12:23:34');
DCL-S timestamp6 TIMESTAMP INZ(Z'1997-02-03-12.45.59.123456');
DCL-S timestamp0 TIMESTAMP(0) INZ(Z'1997-02-03-12.45.59');
DCL-S timestamp1 TIMESTAMP(1) INZ(Z'1997-02-03-12.45.59.1');
DCL-S result VARCHAR(100);
This example formats the time and date with the default formats. Assume that the default formats are both *USA.
result = 'It is ' + %CHAR(time) + ' on ' + %CHAR(date);
// result = 'It is 12:23 PM on 02/03/1997'
This example formats the time and date with the job formats. Assume that the job date format is *MDY- and the job time separator is a period.
result = 'It is ' + %CHAR(time : *jobrun) + ' on ' + %CHAR(date : *jobrun);
// result = 'It is 12.23.34 on 97-02-03'
This example formats the time and date with specific formats.
result = 'It is ' + %CHAR(time : *hms:) + ' on ' + %CHAR(date : *iso);
// result = 'It is 12:23:34 on 1997-02-03'
This example formats the timestamps with separators:
result = %CHAR(timestamp0);
// result = '1997-02-03-12.45.59'
result = %CHAR(timestamp1);
// result = '1997-02-03-12.45.59.1'
result = %CHAR(timestamp6);
// result = '1997-02-03-12.45.59.123456'
This example formats the timestamps with no separators by specifying the ‘&’ separator:
result = %CHAR(timestamp0 : *iso&);
// result = '19970203124559'
result = %CHAR(timestamp1 : *iso&);
// result = '199702031245591'
result = %CHAR(timestamp6 : *iso&);
// result = '19970203124559123456'
You can use %SUBST with the %CHAR result if you only want part of the result:
result = 'The time is now ' + %SUBST (%CHAR(time):1:5) + '.';
// result = 'The time is now 12:23.'