MoveA? Again? Still? Really?
Author's note: The subject of the RPG opcode MoveA (as it pertains to free-format RPG) keeps coming up in articles, blogs, and forums throughout our industry. It's time to put it to rest. The following excerpt from the book Free-Format RPG IV should supply all you need to handle the free-format conversion of this opcode.
Solution for the Fixed-Format MoveA Operation
One of the operations that free-format RPG IV doesn't support is MoveA (Move array). You can perform the equivalent function, however, by using various built-in functions.
History
IBM created the MoveA operation for RPG II programmers, to solve a then-current need for character manipulation. At the time, no Scan (Scan string), Subst (Substring), or Cat (Concatenate two strings) operation existed, and built-in functions were still decades away. MoveA's purpose was to move a character field to an array defined as character with length 1 and a number of elements equal to the length of the field. Inside the array, programmers could scan and change the field using array indexes.
By converting the field to an array, you could perform character searches (scanning) using the array lookup function. The Lookup operation code returns the location found in the array in an index, allowing modification of the array element.
You can use the MoveA operation to load a field starting anywhere in the array, not just in position 1, to imitate a substring function. You can place multiple fields in the array, emulating the concatenation function. Character management is easy if the character locations are available using an index; in this case, the character locations are available in array elements. After performing all character management operations, you can convert the array back to a field, again using the MoveA operation.
Another function of MoveA is moving array data to another array. In the implementation of this function, there is no recognition of array boundaries. The sending array can start at any array index, and the receiving array can start at any array index.
The Free-Format Solution
In RPG IV, if you must move a field to an array rather than manage the field using character-string built-in functions, consider the following:
D Array S 1 Dim(30)
D Field S 30
D i S 2 0
/free
For i = 1 to %len(Field);
Array(i) = %subst(Field:i:1);
Endfor;
To move the array back to the field:
For i = 1 to %len(Field);
%subst(Field:i:1) = Array(i);
Endfor;
In most cases, however, you won't need these two routines because RPG IV provides many good character-management built-in functions.
The free-format emulation of MoveA begins with the %scan built-in function. Finding a single character or small string within a character string is easy using %scan. As an example, if you are locating the small string "qu" in another string, say 'Albuquerque', just specify:
Location = %scan('qu':'Albuquerque');
After this line of code is executed, Location has the value 5. To find the second 'qu', you need some loop logic.
To replace one or more characters in a character string, you can use the %subst or %replace built-in function. Here's an example: Say you want to replace all occurrences of "i" in the character string "Mississippi" with "a". You can use the following routine to do so:
D Search_char S 1 Inz('i')
D Char_string S 30 Inz('Mississippi')
D i S 2 0
/free
i = 1;
Dou i = *Zero;
i = %scan(Search_char:Char_string:i);
If i > * Zero;
%subst(Char_string:i:1) = 'a';
i += 1;
Endif;
Enddo;
Another way to do the same function is to use the built-in function %xlate.
D Search S 1 Inz('i')
D New S 1 Inz('a')
D Char_string S 30 Inz('Mississippi')
/free
Char_String = %xlate(Search:New:Char_String);
To build a long character string from smaller strings, consider the following example of concatenation:
D F1 S 10 inz ('Now')
D F2 S 10 inz ('is')
D F3 S 10 inz ('the')
D F4 S 10 inz ('time')
D String S 50
/free
String = %trim(F1) + ' '
+ %trim(F2) + ' '
+ %trim(F3) + ' '
+ %trim(F4) + '.';
The %Subarr Built-in Function
Moving the data of an array to an array is a bit trickier than some of the operations examined above. V5R3 provides a new built-in function, %subarr, that helps get the job done.
Let's look at an example where an element of an array is defined as 100 bytes, and another array is defined as length 1 with 100 elements. We want to move all elements of the 100 element array (Array1) to the element of Array2, whose index is i. The fixed-format scenario would be as follows:
D Array1 s 1 Dim(100)
D Array2 s 100 Dim(50)
D i s 5U 0
D j s 5U 0
D Arx s Dim(100)
D Like(Array1)
D Based(Ptr)
C Movea Array1 Array2(i)
To perform the same operation in free-format, you have two alternatives:
/free
For j = 1 to %elem(Array1); //
%subst(Array2(i):j:1) = Array1(j); // Move 1 char
Endfor;
// Another solution using %subarr and a based array
// template
Ptr = %addr(Array2(i)); // Ptr to Array2 element i
Arx = %subarr(Array1:1); // Move array to array
LATEST COMMENTS
MC Press Online