Today I ran into this problem: if an external file named CONTROL has a data structure scoped over it, and that structure contains a field called F00001, how can I break it into subfields?
It's actually a classic IBM i problem: you’ve got a big ugly field like F00001 in the CONTROL file, and you want to break it into meaningful subfields inside your RPG data structure. Whats the best way to do this?
Well... if the field comes from an ExtName() external DS, you cannot directly redefine it inside the same DS. But you can break it into subfields using a nested DS with Overlay().
The correct RPG way: create a nested DS with OVERLAY on the external field
Assume CONTROL has:
F00001 20A
You can split it like this:
Dcl-Ds DS_CONTROL ExtName('CONTROL') Qualified;
End-Ds;
// Now redefine F00001 into subfields
Dcl-Ds F00001_SPLIT Qualified Overlay(DS_CONTROL.F00001);
Part1 Char(5);
Part2 Char(3);
Part3 Char(12);
End-Ds;
Now you can reference:
F00001_SPLIT.Part1F00001_SPLIT.Part2F00001_SPLIT.Part3
All mapped over the original F00001 bytes.
Why this works
ExtName('CONTROL') loads the external fields exactly as they are. You can’t change their definitions, but you can create a second DS to overlay the original field. Overlay() lets you reinterpret the bytes in any way you choose.
Example with real-world meaning
Say F00001 actually contains:
Customer type (1 char)
Region code (2 char)
Account number (10 char)
Status flag (1 char)
Filler (6 char)
You can map it like this:
Dcl-Ds F00001_SPLIT Qualified Overlay(DS_CONTROL.F00001);
CustType Char(1);
Region Char(2);
AcctNumber Char(10);
Status Char(1);
Filler Char(6);
End-Ds;
Now you can write:
If F00001_SPLIT.Status = 'A';
// Active account
EndIf;
Important rules
The overlay DS must be separate from the ExtName DS: You cannot put the overlay inside the same DS.
The total length of the subfields must equal the original field length: Otherwise the compiler complains.
You can overlay numeric fields too: Just use zoned/packed definitions that match the bytes.
