rpgc runs classic fixed-column RPG programs that rely on the fixed-logic program cycle - the implicit read/calculate/output loop driven by a primary input file, with no explicit READ and no DOW/DOU loop in the calculations.

A program is compiled as a cycle program when it declares a primary input file (an F-spec with file designation P). The cycle then, on each iteration: writes 1P heading and detail output, reads the next primary record (setting its record-identifying indicator; end-of-file turns on LR), runs total-time calculations and total output, tests LR to end the program, moves the record's fields into the program field area, and runs detail-time calculations. Programs with no primary file are unaffected and follow the ordinary linear path.

Supported in the cycle

Output edit codes

Code Effect
Z Zero-suppress: strips leading zeros, the decimal point, and the sign, printing all significant digits of the field - the integer and fractional digits run together (e.g. 000033; a (9,2) field holding 12.341234 and 1212000.00121200000). The fractional digits are kept; only the decimal point is removed.
1 Leading-zero suppression with a decimal point and grouping commas, a printed zero balance, and no sign (e.g. 0003750 at 2 decimals → 37.50; 1234.501,234.50). Negatives print unsigned.

A combination-edited numeric field (codes 1-4) occupies its full edited width on the print line - the integer digits, the grouping-comma positions reserved for them, the decimal point, and the fractional digits - right-justified at the O-spec end position with the suppressed leading positions blank-filled. For example a PACKED(9,2) field edited with code 1 always occupies 12 columns (9,999,999.99 form), so a value of 37.50 renders as seven blanks followed by 37.50. Those leading blanks overwrite any earlier output field that ends within the edited field's column span, matching IBM i.

Output field types

Beyond character and packed/zoned/integer/unsigned numeric fields, an O-spec output field may name a FLOAT or a date / time / timestamp field, each rendered in its IBM i external form:

A field whose type has no character external form (for example a pointer) is rejected with diagnostic TRN3030 rather than printed as blanks.

Running a cycle program (injectable input source / printer sink)

Like the pluggable screen handler, a cycle program is headless and testable. It exposes an injectable input source and printer sink so callers and tests supply records and capture output without argv or spool files:

SALES prog = new SALES();                          // ready to run
prog.setCycleInput(new FlatFileInput(reader, 80)); // primary-file records
prog.setCyclePrinter(line -> captured.add(line));  // report lines
prog.setOverflowLine(60);                          // optional: default is 60
prog.run();                                         // runs the whole cycle

For matching-record programs with a secondary file:

CYCLEMR prog = new CYCLEMR();
prog.setCycleInput(new FlatFileInput(primaryReader, 40));    // primary file
prog.setSecondaryInput(new FlatFileInput(secondaryReader, 40)); // secondary file
prog.setCyclePrinter(line -> captured.add(line));
prog.run();

With more than one secondary file, address each by its zero-based position in F-spec order:

prog.setSecondaryInput(0, new FlatFileInput(firstReader, 40));  // first IS file
prog.setSecondaryInput(1, new FlatFileInput(secondReader, 40)); // second IS file

new SALES() is ready to run with sensible defaults: the printer writes to standard output, and (in main) the primary file is read from the path given as the first command-line argument, or a file named after the primary file with a .DATA suffix. Each declared secondary file defaults to a file named after it with a .DATA suffix. The cycle runs to completion inside run(); callers never step it. The boundary types are plain strings (the fixed-width input record and the rendered print line); no marshalling is performed.