Skip to content

Program Described Files I Specs and O Specs

Daniel Long edited this page Sep 29, 2026 · 2 revisions

Program-Described Files (I-Specs and O-Specs)

Everything in the Record-Level Access chapter runs against a database table over ODBC. Program-described files are the other kind: flat files with a byte-position field layout, described by I-specs and O-specs rather than by an external descriptor. They are available from fixed-format source only.

The On-Disk Format

Real IBM i program-described files are pure fixed-width bytes on a record-oriented file system, which has no equivalent on macOS, Linux or Windows. OpenRPG uses a portable convention instead: one record per line — exactly the declared record length in bytes, right-padded with spaces or truncated to fit, followed by a newline. Fixed width makes byte-offset seeking for UPDATE trivial.

Numeric fields are stored as plain ASCII digits, right-justified and zero-padded, with an implied decimal point and an optional leading -. This is an OpenRPG interchange format, not literal IBM i on-disk semantics.

A Complete Example

     HDFTACTGRP(*NO)
     FTESTFL154 UF A F   25        DISK
     DTMPDSP           S             52A
     ITESTFL154 AA
     I                             A    1   20  NAME
     I                             S   21   25 0AGE
      /free
       NAME = 'Alice';
       AGE = 30;
       EXCEPT;
       NAME = 'Bob';
       AGE = 25;
       EXCEPT;
       NAME = 'Carol';
       AGE = 40;
       EXCEPT;
      /end-free
     C                   READ      TESTFL154
     C                   DOW       NOT %EOF(TESTFL154)
     C                   EVAL      TMPDSP = %TRIM(NAME)
     C     TMPDSP        DSPLY
     C                   EVAL      TMPDSP = %CHAR(AGE)
     C     TMPDSP        DSPLY
     C                   READ      TESTFL154
     C                   ENDDO
     C                   RETURN
     OTESTFL154 EADD
     O                       NAME                20
     O                       AGE                 25

The F-spec says UF A F: an update file (position 17), full procedural, read with operation codes (18, required for input and update files, IBM: RNF2093), records may be added (20), and F in position 22 for program-described. The record length is in positions 23-27. Field names from the I-spec become ordinary program variables. Specifications come in the order H, F, D, I, C, O (IBM: RNF0257).

I-Spec — Input Layout

An I-spec file has one record identification line per record type, optionally followed by field description lines.

Record identification:

Positions Field
7-16 File name
21-22 Record identifying indicator
23-30, 31-38, 39-46 Up to three identification code sets

Each code set is a position, an optional N, a code part and a character — which together say "the byte at this position is (or is not) this character". Only code part C (character) is supported; the EBCDIC-era zone (Z) and digit (D) tests are rejected.

Field description:

Positions Field
36 Data format
37-41 From byte position
42-46 To byte position
47-48 Decimal positions
49-62 Field name
63-64 Control level (L1-L9)
69-70 Plus indicator
71-72 Minus indicator
73-74 Zero-or-blank indicator

Date, time, timestamp, graphic and indicator formats (D/T/Z/G/N) are rejected at parse time — a CHAR field still works fine for date text if you do not need real date parsing.

Control levels in positions 63-64 parse and are accepted, but do not yet set anything at run time.

O-Spec — Output Layout

Output records are exception records: E in position 17 of the record line (IBM requires a type there, RNF6005), written by the EXCEPT operation. ADD in positions 18-20 adds a new record; without it, a record for an update file rewrites the one last read. An EXCEPT name in positions 30-39 lets a program write one record and not another. The heading, detail and total types (H, D, T) are written by the RPG cycle, which OpenRPG does not implement.

Each record line is followed by one field or constant line each:

Positions Field
30-43 Field name — blank if a constant is given instead
44 Edit code
45 Blank-after (B)
47-51 End position
53-80 Constant or edit word

Field width is inferred from the gap to the previous field's end position, not from the field's own declared length. End positions must be absolute — the relative +n/-n forms are not supported. Edit codes use the same engine as %EDITC, and the end position must leave room for what the edit code adds (IBM: RNF8003).

     OTESTFL157 EADD         NEWNOTE
     O                       NOTE                20
     OTESTFL157 E            CHGNOTE
     O                       NOTE                20

EXCEPT NEWNOTE adds a record; EXCEPT CHGNOTE rewrites the one just read. EXCEPT with no name writes the records that have none.

Supported Operations

Opcode Behavior
READ Sequential read, dispatching on record type
EXCEPT Write the E output records: add, or rewrite the record just read

WRITE and UPDATE on a program-described file take a data structure holding the record on IBM i (RNF5191 without one), which OpenRPG does not support; use EXCEPT. CHAIN, SETLL, SETGT and DELETE are not supported on program-described files — keyed access needs F-spec key-field columns that are not modeled for them. O-spec spacing and skipping, and printer paging, are also unavailable; there is no PRINTER runtime in this compiler for any file type.

A program writes READ MYFILE; regardless of which kind of file MYFILE is — the compiler picks the flat-file or the RLA path from the declaration.

Clone this wiki locally