One challenge when switching from fixed- to free-format RPG IV is the disappearance of many frequently used op-codes. This tip reveals what to do for six of the lost operations.
Commonly used operations for character manipulation in fixed-format are SCAN, SUBST, CAT, MOVE, MOVEL, and MOVEA. These operations are not available in free-format. This tip demonstrates how to do these operations in the free-format way.
SCAN: A built-in function (BIF) %scan is available that performs the scan function. The only difference between the SCAN op-code and the BIF is that the BIF does not have the array option that the SCAN op-code has. Otherwise, they are identical.
Example: Assume field CITY contains 'ALBUQUERQUE'.
'QU' SCAN CITY:6 ANS
After this operation, ANS contains a 9, because we started the scan in position 6.
The free format equivalent would be:
ANS = %scan('QU':CITY:6);
SUBST: This op-code was also replaced with a BIF: %subst. The SUBST operation can only substring a source string, but the %subst BIF can substring both a source and a target string.
Example: Assume a field named STR has a value of 2, and field NAME has a value of 'JONATHAN SMITH'.
3 SUBST NAME:STR ANSW
After this operation, ANSW contains 'ONA'.
The free format equivalent would be this:
ANSW = %subst(NAME:STR:3);
CAT: Concatenation is performed in free-format by using the plus symbol (+) in a string expression. The following example shows both the fixed-format method of building an address line and the free-format equivalent:
D City s 15 Inz('Chicago')
D State s 2 Inz('IL')
D Zip s 5 Inz('60601')
d Line4 s 30
c Movel City Line4
c Cat ',':0 Line4
c Cat State:1 Line4
c Cat Zip:2 Line4
Line4 = %trim(City) + ', ' + State + ' ' + Zip;
MOVE: This op-code has many functions available, but I will limit my discussion to the character-handling part. For this operation, the Factor 2 field is right-adjusted in the result field, with left blank fill optional. There is no exact match in free-format, in a BIF or other operation, but whatever is needed can be accomplished.
For a right-adjust move with left blank fill (padding), the EVALR operation is the solution in free-format.
Example: Assume field ALPHA is 'ABCDEFGH' and field NAME is 'JOE'.
The fixed format operation…
MOVE(P) NAME ALPHA
…would have an equivalent in free format of…
EvalR ALPHA = NAME;
Without blank fill, the fixed format operation would be…
MOVE NAME ALPHA
The field ALPHA would now be 'ABCDEJOE'.
The equivalent in free-format can be done several ways, and here's one way:
ALPHA = %replace(NAME:ALPHA:%len(ALPHA) - %len(NAME) + 1);
MOVEL: As with MOVE, there is no exact match in free-format, but the functionality is easy to duplicate. In MOVEL, Factor two is left-justified in the Result field.
Example: Assume field ALPHA is 'ABCDEFGH' and NAME is 'JOE'.
MOVEL NAME ALPHA
The field ALPHA now contains 'JOEDEFGH'.
The equivalent in free-format would be…
ALPHA = %replace(NAME:ALPHA);
MOVEA: There is no move array operation in free-format. However, there's always some way to duplicate the function needed.
The MOVEA operation was first available in RPG II, and it helped solve a big need for character scan, concatenation, and sub-stringing that was previously unavailable. By moving a field to an array defined as one character per element, scanning became available using the LOOKUP operation. If an element is found, the index resulting from the LOOKUP is then used to modify the array element to whatever is desired.
Since we now have scanning (%scan), translate (%xlate), concatenation (+), and sub-stringing (%subst) of character fields, the old technique of using MOVEA is not needed or desirable.
Using MOVEA to move an array to another array is a bit trickier to do in free-format, and not as elegant, but nonetheless possible.
Here are examples:
D Ary1 s 1 Dim(100)
D Ary2 s 100 Dim(50)
D i s 5u 0
D j s 5u 0
D Arx s Like(Ary1) Based(Ptr)
* Move all elements of Ary1 to element i of Ary2:
c MoveA Ary1 Ary2(i)
// Free format Method 1:
For j = 1 to %elem(Ary1);
%subst(Ary2(i):j:1) = Ary1(j);
// Free Format Method 2;
Ptr = %addr(Ary2(i)); // Point to correct element in Ary2
Arx = Ary1;
There are many other operations in fixed-format that are not available in free-format, but there's always an equivalent programming method available.