Supported RPG Features

The EXTFMT(code) keyword specifies the external representation used when a compile-time or pre-runtime array is loaded from its file. The keyword is accepted in both free-format and fixed-format:

DCL-S myArr PACKED(5:0) DIM(3) CTDATA EXTFMT(S);

The parameter is one of nine external formats:

Code External representation
S Zoned decimal - one digit per byte, sign in the last byte's zone
P Packed decimal - two digits per byte, sign in the final nibble
B Binary - big-endian two's complement
I Integer - big-endian two's complement
U Unsigned - big-endian, no sign bit
L Zoned digits preceded by a separate +/- sign character
R Zoned digits followed by a separate +/- sign character
F Float - big-endian IEEE 754 at the field's own width (4 or 8 bytes)
C UCS-2 - applies to a UCS-2 array only, never to a numeric one

EXTFMT describes data arriving from outside the program, so it belongs only on an array that has some: one with CTDATA, FROMFILE or TOFILE. Writing it on a run-time array warns (TRN1070) and is ignored, as does writing it on a float array (TRN1071) or naming a parameter that is not one of the nine (TRN1069). EXTFMT(C) on a numeric array warns as TRN1072. Each is a warning - the keyword is ignored and the program is still created.

On a CTDATA array only S, L and R are valid, because the source records are character text; any other parameter warns (TRN1068) and is ignored.

For a numeric CTDATA array the source records are zoned-external digit characters: the array's declared decimal positions are an implied decimal point (not written in the data - 205 in a PACKED(3:1) array loads as 20.5), each element is the declared number of digits wide (so PERRCD and ALT split a record by digit count), and a negative value carries its sign as the EBCDIC zone overpunch on the last digit (12N loads as -12.5).

EXTFMT(L) and EXTFMT(R) change that last part: the sign is a + or - character of its own rather than an overpunch, so each element occupies one source position more than it has digits. A two-digit array written with EXTFMT(L) spends three positions per element, and PERRCD splits the record accordingly:

     D Updates         S              2P 0 DIM(4) PERRCD(4) CTDATA EXTFMT(L)
**CTDATA Updates
+37-38+52-63

That loads 37, -38, 52, -63. With EXTFMT(R) the same values are written 37+38-52+63-.

EXTFMT on a pre-runtime (FROMFILE) array

On a pre-runtime array the keyword does real work: it says how to read the bytes of the field in the table file, which the file's column type does not record. A CHAR(3) column may hold x'12345F' - that is the packed decimal 12345, not text - and EXTFMT(P) is what says so:

     FSALESTBL  IT   F    3        DISK
     DRates            S              5P 0 DIM(2) FROMFILE(SALESTBL) PERRCD(1)
     D                                     EXTFMT(P)

rpgc reads the field's bytes and decodes them per the code, using the whole table in the section above. The array's declared decimal positions supply the implied decimal point, as for CTDATA - except under EXTFMT(F), where the float carries its own exponent and the declared positions do not apply.

Two of the codes are distinguished only by how they read the same bytes, so it is worth being explicit: B and I are signed, U is not. The field x'C1C2' loads as -15934 under EXTFMT(B) and as 49602 under EXTFMT(U). Likewise L and R expect a +/- character in a byte of its own, making the field one byte wider than its digit count - x'60F1F2F3F4F5' is -12345 under EXTFMT(L).

Bytes that are not valid for the declared format - a bad digit or sign nibble - raise a decimal-data error, %STATUS 00907, rather than loading a fabricated number. See Invalid Numeric Field Data.

A table file whose column is already a proper numeric type (DECIMAL, NUMERIC, an integer type) needs no EXTFMT: the value is read directly and the keyword would only restate what the column already says.

Pre-runtime arrays are a fixed-format construct - FROMFILE/TOFILE on a free-form DCL-S are rejected - so this form of EXTFMT appears only on D-specs.