IBM i track · Core · self-paced ~25–30h (5 days as a cohort) · prerequisite: CS201
Modern free-format RPG IV (ILE RPG), taught from the development loop up: program anatomy and the compile listing, CL as the glue, fixed-format read at sight, packed and zoned decimal byte by byte, data structures and real date types, built-in functions, eval(h) and monitor, control flow and the main-loop pattern, then the integrated database — dcl-f, read and %eof, chain, setll and reade, write/update/delete with (e) and %error — arrays and %lookup, /copy, subprocedures, modules and service programs. 56 short videos (about 7.3 hours), each a lesson, a live demo and your own exercise on the same environment, ending in ORDPOST, a production-shaped batch application built to the same spec as the COBOL course’s capstone — one problem, two platforms.
Self-paced available Cohort
Recorded: Sessions 1–4 in full and Session 5’s videos 5.1–5.5 — 34 of the 56 lesson videos, about five hours in all. Coming soon: 5.6–5.9 (report lines, page control, OVRDBF and the complete report lab), Session 6 (arrays), Session 7 (/copy, subprocedures and ILE) and the Session 8 ORDPOST capstone; their lessons and labs are published below now. Enroll now and start with Sessions 1–5; the remaining videos are released session by session. Where this environment differs from a production IBM i, the video says so on camera rather than faking it.
Every session ends in a lab on your own environment. Labs are machine-checked against expected outputs — you and your L&D team always know exactly where you stand.
Seven videos, each a lesson, a live demo and your own exercise on the same environment. RPG then and now: the punched-card report generator and today’s free-format RPG IV, why you write free-format and must read fixed-format, and the **FREE marker (and the older /free you will meet in real members). Where programs live: source member → CRTBNDRPG → *PGM object → CALL, the listing’s verdict, and why no object is created on failure. The anatomy of a free-format program — ctl-opt, dcl-s/dcl-ds/dcl-f, the main calculations, *inlr = *on and return — and the famous persisted-variable gotcha when *inlr is left off. DSPLY, the job log as the program’s diary (read it before changing code) and debugging by print. The compile listing as a map: the sections of a real IBM i listing and the cross-reference as the fastest way through a legacy program you have never seen. CL in one video: PGM/ENDPGM, CRTBNDCL, CALL, SBMJOB and an OVRDBF preview — every real batch process is a CL driver calling RPG workers. Reading fixed-format H/F/D/C specs at sight-reading level, indicators named, and the conversion mindset: every fixed line has a free equivalent. Live on the system: CUSTRPT, a real mixed member — a fixed-format F-spec above free-format logic — opened in SEU; a clean compile and CALL (“Hello from RPG IV”), then a planted error with the listing’s exact message and line and no *PGM created; an eleven-line program built from an empty member, compiled and called; a divide by zero ending the program with SNX0102 and its story read top to bottom in DSPJOBLOG; a where-is-this-field-set hunt through the numbered source and the repository’s field cross-reference; a five-line CL driver compiled, called interactively, then submitted to QBATCH and its output found in the batch job’s log; a fifteen-line pure fixed-format program and its free-format translation compiled side by side with identical output. Honest notes from the recording: this environment re-initialises variables on every CALL, so the *inlr-off persistence is taught and shown as it behaves on a real box; its compile listing carries the header, numbered source and verdict without the options, cross-reference and message-summary sections; and its DSPLY does not truncate at 52 characters.
LAB Sight-recognition worksheet: eight snippets labelled fixed or free, four fixed lines matched to their free equivalents. Compile the supplied member, CALL it, break it deliberately and record the message ID, line number and severity, then fix it. Write, compile and CALL a program that DSPLYs your name and course start date — clean by the second attempt. Diagnose the supplied failing program from the job log alone, in two sentences, then fix it. Cross-reference scavenger hunt: three where-defined / where-modified / which-file questions answered with line numbers. Write a CL driver for your program, run it interactively and via SBMJOB and capture both job names. Translate a twelve-line fixed-format routine to free format; outputs must match. Session 1 checkpoint: the loop, and both dialects readable.
Eight videos. dcl-s and the type system: char and varchar, packed and zoned, int, date/time/timestamp and ind, inz() and naming. Packed and zoned nibble by nibble — the flagship data video, deliberately parallel to the COBOL course’s: one digit per byte with the sign in the last zone versus two digits per byte with the sign nibble last, (digits+1)/2 bytes, +12345 as 12 34 5C, and why packed(7:2) has no byte for the point. Why decimal types exist: floating point cannot hold 0.10, business math must be exact, and the decision table — packed for money and quantities, zoned for legacy interchange, int for counters, float practically never — with DB2 for i DECIMAL columns being packed. dcl-ds data structures, qualified as the modern default, likeds to clone a shape. Overlays and redefinition with overlay(target:pos) and pos — two views over the same bytes, a date split into year, month and day, and the warning that changing one view changes the other. Real date types with real semantics: *ISO, arithmetic and validation built in, and the legacy chore of numeric pretend-dates. Named constants with dcl-c, like() for a field shaped like another, and templates with likeds. Live on the system: every type declared and DSPLYed with its real value — packed(7:2) +00009.95, zoned(5:2) +012.50, int +000000003, ind 1; packed versus zoned byte sizes read from DSPFFD buffer offsets (a 7P2 in four bytes beside a 7S2 in seven; BALANCE 9P2 in five); 0.10 + 0.20 exactly 0.30 in packed beside the real IEEE float drift, 2.999999999999999E-001; a qualified customer DS and an order-line DS filled and displayed; a YYYYMMDD field split by overlay with the view semantics proven (change the month and the whole field changes); %date(20260315:*iso) + %days(30), %diff in days and a month-end clamp from + %months(1); three magic numbers refactored to dcl-c and a like() field inheriting its type; and the Session 2 exit exam, ORDREC — one program using the whole toolkit at once (a constant, a qualified DS, char, packed and int, two real dates, a like() field and an overlay-split reference) — compiled clean with every value displayed. Honest notes from the recording: on this environment typed date literals (d'2026-03-15') do not compile, so dates are built with %date(num:*iso); the engine does not expose raw hex, so the nibble layout is taught on the board and proven through DSPFFD byte sizes; and dcl-c constants are not enforced read-only — each difference is stated on camera.
LAB Predict-then-verify six declarations with inz values: what DSPLY shows and how many bytes each takes, checked against the listing. Decode four packed hex dumps to value and sign by hand, then declare them and verify. Type-selection worksheet: eight described fields, a type and a one-line reason each. Define the item DS per spec, load one item with inz and DSPLY every subfield. Phone number char(10) with overlays for area, prefix and line. Declare a date, a time and a timestamp, display each, then try to force February 30th in and document what happens. Refactor a program with five magic numbers and duplicated declarations using dcl-c and like(); identical output required. Lab 2.8, the record layout: a customer account record — account, name, type code, balance and credit limit packed(9:2), status with named-constant values, open date as a real date — sketched field by field with the bytes totalled by hand, then coded as a qualified DS with one sample customer and every value displayed. This DS becomes the database record in Session 5. Session 2 checkpoint.
Seven videos. Assignment as the universal MOVE: char padding and truncation, decimal alignment, the silent high-order loss, evalr, and MOVE/MOVEL in fixed form as recognition only. Arithmetic and precedence, integer versus decimal division, %div and %rem, and intermediate-precision awareness. eval(h) for half-adjust at the target’s precision; overflow and divide by zero as runtime exceptions; monitor / on-error / endmon as the structured ON SIZE ERROR — every division sits inside protection. Built-in functions I, the character toolkit: the %trim family, concatenation, %subst, %scan, %replace, %len, %upper and %lower. Built-in functions II, numeric and conversion: %dec with monitor as the validation idiom of the whole platform, %char, %int, %abs, %editc and %editw introduced — validate with monitor + %dec, compute in packed, format out with %editc. Formatting output: %editc codes, %editw edit words, why edited output is display-only, and %char with date formats for the pretend-date round trip. Live on the system: ‘HI’ padded and ‘HELLO’ truncated into char(5), 254.00 and a cross-precision packed(9:2), 12.75 into an int truncating to 12, MOVEL ‘ABCDE’ → ABC; 2+3*4 versus (2+3)*4, 2**3, 17/5 packed versus int, and the real intermediate-truncation bug — 10/3*3 = 9.99, the cent that vanishes; 2/3 as 0.66 without and 0.67 with eval(h); a raw divide by zero halting the job versus the same inside monitor (“caught div0”, %status 102, then “after monitor”); all twelve character BIFs on real fields, %len of fixed versus varchar; %dec on ‘42.75’ converting and on garbage caught by on-error without a halt, %dech and %inth rounding; %editc(‘A’) producing 1,234,567.89 and 1,234.56CR for a negative, %editw with a fixed-separator mask (123-45-6789), %char(date:*usa) giving 08/31/2026; and the Session 3 lab run as a real pay stub — GROSS 985.63, TAX 147.84, NET 837.79, a guarded division. Honest notes from the recording: on this environment %subst needs its three-operand form, %dech, %inth and %editw results must be assigned to a field before DSPLY, and money-style %editw masks misplace separators — so money is taught through %editc and %editw through fixed layouts, stated on camera.
LAB Predict-then-verify six assignments across sizes and types, including one silent digit loss you must catch. Total seconds to HH:MM:SS with %div and %rem, three hand-checked values. Sales tax with eval(h), and unit price = total/qty that survives qty = 0 via monitor with a readable message. One formatted display line from the Session 2 customer DS — trimmed name, account, a slash-formatted date via %subst. The validate-convert-compute chain for two char inputs, rejecting garbage with a message. Format the customer for display: balance with commas and two decimals, credit limit, open date as dd/mm/yyyy, tested with a negative and a zero. Lab 3.7, the pay calculator: hours with overtime beyond 40 at 1.5×, rate, gross, a flat-percentage tax with eval(h), net — packed throughout, one edited pay line, division and conversions guarded by monitor; tested at 40, 45 and 0 hours. Kept — Session 4 adds control flow to it. Session 3 checkpoint.
Seven videos. if / elseif / else / endif as full block structure, ind fields as flags, and the same rule in indicator-style fixed form beside it — you will read that, you will write this. Conditions and validation patterns: and/or/not with parentheses, the validation stack (monitor + %dec, range, blank checks, %check) and set-a-flag-and-message discipline. select / when / other for the multi-way branch: first match wins, no fall-through. Loops: dow (test before), dou (test after), for with by and downto, iter and leave, and the infinite-loop autopsy — what a looping interactive job looks like in WRKACTJOB and how to end it. Structure with begsr/endsr/exsr subroutines and *INZSR, named phases and a short mainline, and the honest limit that subroutines share every variable — the reason Session 7’s subprocedures exist. The main-loop pattern — initialise, prime, loop (process, advance), finalise — taught one session before files make it real, as the twin of the COBOL course’s priming-read lesson. Live on the system: a grader branching 95 → A, 83 → B, 68 → F and a nested if upgrading 100 to PERFECT, all six comparison operators; a or b and c with and without parentheses changing the result, %check finding a bad character, a three-rule validator rejecting a blank name, an out-of-range age and a bad status; select/when dispatching A, H, I and X with other firing, and two identical when branches proving first-match-wins; dow, dou, for, for … by, leave and iter each summing to the predicted totals; three subroutines called from a short mainline with *INZSR running first; an init → loop → terminate run over five items to TOTAL 150; and the Session 4 lab run live — five orders, one rejected for a zero quantity, SUMMARY OK 4 BAD 1. Honest note from the recording: on this environment a for loop that indexes an array fails to compile (SFF6301), so array-driven forms wait for Session 6, and the loop terminator is spelled enddo, not enddow — stated on camera.
LAB Add the overtime rule and a minimum-wage floor to your 3.7 pay calculator with if/elseif/else. Validate routines for account number (numeric, five digits), type code (one of a constant set) and amount (numeric, above zero) against the supplied four-record set with published messages. Letter grades via select/when with range conditions and other catching invalid scores, tested at the boundaries (89.9, 90, 100, 101). Compound interest: for-loop a balance until it doubles, the dow version too, then deliberately create, observe and end one infinite loop of your own from WRKACTJOB. Restructure your 4.1 program into a short mainline with init/process/wrapup subroutines. Trace-prediction worksheet on a supplied main-loop program for a three-record run, then run it with tracers and self-grade. Lab 4.7, structure + logic: the pay calculator extended to five hard-coded employees, select/when tax brackets, the full validation from 4.2, subroutine structure and the main-loop shape — clean compile, correct totals, at least one rejection displayed. The last DSPLY-only program; the database arrives next. Session 4 checkpoint.
Coming soon Videos 5.6–5.9 — report lines, page control and totals, OVRDBF with the CL driver, and the complete report lab — are coming soon; 5.1–5.5 are recorded, and the lab spec is below.
Nine videos. There is no file system, only the database: physical files are DB2 for i tables, DDS describes the record format, fields and key, logical files are keyed views over physicals, and new tables are born as SQL while DDS is the installed base you will read for decades. dcl-f: usage(*input / *output / *update / *delete), keyed, and externally described files — the compiler reads the DDS and defines every field for you, no copybook needed, the database as the single source of truth (contrast the mainframe’s FD + copybook, explicitly). read and %eof as the priming loop made real, setll *loval, and the level check that refuses to run a program whose compiled layout no longer matches the file. Keyed access as the normal case: chain and the %found discipline (never touch fields after a failed chain), setll/reade for key groups, setgt, and the design instinct — one record → chain, one group → setll + reade, the whole file → the sequential loop. write, update and delete, read-for-update, duplicate keys, and the (e) extender with %error and %status on every I/O — the FILE STATUS discipline of this platform, and what separates production code from coursework. Then program-described report lines with the %BIF formatting chain, headings and the one-door output routine; page control and grand totals with the self-check habit; OVRDBF in the calling CL pointing the program’s file at a different physical file — test versus production without recompiling, the library list as the other half, both as the platform’s answer to JCL DD statements; and the complete report lab. Live on the system (5.1–5.5): CUSTPF, ORDPF and the logical ORDLF as PF-DTA and LF objects, CUSTPF’s DSPFFD (record length 43, BALANCE PACKED 9,2 at byte 39) and its rows in STRSQL; dcl-f custpf importing custno, custname, city and balance with no dcl-s, and a bogus field name caught by the compiler; a priming read loop printing every row in order, COUNT 4 TOTAL 132901.61; chain by key fetching one customer directly, a bogus key leaving stale fields behind when %found is ignored, setll/reade walking exactly one customer’s three orders over a keyed file built live from DDS with CRTPF, setgt skipping the group, setll *loval rewinding; write proved by chaining the new record back, update’s new values read back from the database, delete proved by a failing chain, a raw duplicate-key write ending the job on SNX1021 versus write(e) continuing with %status 1021, %error reset by the next clean write, and the file restored to its starting count on camera. Honest note from the recording: this environment does not refuse an update issued without a prior read (a real IBM i raises status 1211), so read-before-update is a rule you enforce with chain + %found — stated on camera rather than hidden.
LAB From the supplied DDS: field names, types and key on a worksheet, one SELECT, and confirmation that your Session 2 DS matches the record layout field for field. Skeleton program with dcl-f on the customer file keyed, compiled clean, every imported field listed with its type from the listing alone. Read the customer file end to end and display the count — it must match the published number. Lookup routine: chain three supplied account numbers with a %found-guarded not-found message, then all orders for one customer via setll/reade, the count checked against the file. Maintenance mini-program: add a customer, update its credit limit, chain to verify, delete it — every operation (e)-guarded, the file ending exactly as it began. Extend your reader with detail lines and a two-line heading, then page breaks and grand totals cross-checked to the count. A CL driver that OVRDBFs your report to the five-record test file and SBMJOBs it, then the full file interactively — one *PGM, two datasets, zero recompiles. Lab 5.9, the complete report program: active customers only, edited money, headings and page control, grand totals, every I/O (e)-guarded, subroutine structure, a CL driver with OVRDBF for the test file, submitted to batch — published expected totals, and the batch job’s spooled report among the deliverables. Direct ancestor of the capstone. Session 5 checkpoint.
Coming soon The six Session 6 videos (6.1–6.6) are coming soon; the lessons and the lab spec are published here now.
Six videos. Arrays with dim, 1-based subscripts and the out-of-bounds runtime error — an error here, not silent corruption, against the mainframe’s S0C4 for dual-track students; compile-time ctdata arrays for fixed lists versus runtime-loaded arrays. Loading reference tables from the database with a loaded count and an overflow guard, and why rate data lives in files, not code. DS arrays — dcl-ds … qualified dim(50) — as the modern table, one array of records instead of parallel scalars. %lookup for searching without loops, the zero check that is never optional, ascend-declared arrays and the trust warning (declare ascend on unsorted data and get garbage quietly — the shared trust demo with the COBOL course’s SEARCH ALL), sorta, and %lookupgt / %lookuplt for range problems. Multi-dimension thinking with a DS array whose element contains an array, nested for loops and the cross-foot check. Then the table-driven report lab.
LAB A seven-entry day-name array with a bounds check before the reference. Load the supplied rate file into arrays, display every entry, and prove your overflow guard with the oversized file. Convert the loader to a DS array with identical output. A %lookup rate routine with one hit and one miss, then break and fix the sort order as demoed. Four regions × three products: row totals, column totals and a cross-footed grand total that must match both ways. Lab 6.6, table-driven reporting: the Session 5 report loads the rate table at init (guarded, sorted), %lookups each customer’s type for a rate, computes a fee with eval(h), reports and totals the fees, and reports unknown types as errors — published expected totals. Session 6 checkpoint.
Coming soon The six Session 7 videos (7.1–7.6) are coming soon; the lessons and the lab spec are published here now.
Six videos. /copy for shared source — constant sets, procedure prototypes and DS templates — with the honest scoping that record layouts here come free from externally described files, so /copy’s biggest job is interfaces. Subprocedures at last: dcl-proc / dcl-pi / end-proc with parameters, return values and local variables, prototypes as the caller’s contract, and why logic becomes testable, nameable, reusable units. Parameters by reference, by value and const, options(*nopass / *omit) previewed, and the mismatch bugs cured by prototypes shared from /copy members on both sides — the same shape as the COBOL course’s parameter-copybook lesson. ILE named properly: CRTRPGMOD compiles a module, CRTPGM binds modules into a program (compile-then-link-edit rediscovered), CRTBNDRPG as the one-step shortcut, and bind-by-copy staleness. Service programs: procedures bound by reference, fix once and every caller benefits, binder language and binding directories in one gentle pass, and the UTILS service program every shop has. Then the shared-logic refactor lab — the capstone’s architecture.
LAB A constants copy member, with 6.6 converted to use it and the expansion verified in the listing. isValidDate(yyyymmdd) returning ind, tested from a driver with two good and two bad dates. Harden it with const, the prototype in your copy member and a deliberate mismatch caught at compile time. Build it as a separate module bound into your driver; document the three commands and the objects each produced. Your own UTILS service program with isValidDate and one bonus procedure, your driver bound to it, and the fix-once flow shown by changing a message text and re-running the unchanged driver. Lab 7.6, the shared-logic refactor: constants and prototypes from /copy members, fee calculation and date validation as procedures in UTILS, the mainline reduced to orchestration, a nonzero outcome if any record was rejected — and output identical to 6.6, because a refactor changes structure, never results. Session 7 checkpoint.
Coming soon The six capstone videos (8.1–8.6) are coming soon; the full ORDPOST spec and lab are published here now.
Six videos building ORDPOST: a CL driver (with OVRDBF for the test environment) submits an RPG worker that reads a transactions file, validates every record — numeric and domain checks, the account by chain to the customer master, the type by rate-table %lookup, the date by the UTILS service program — computes a fee with eval(h) from the rate table, writes a formatted posting report with headings, pages and totals, writes rejects to an error file carrying the whole original record plus a reason code so they can be fixed and resubmitted, reconciles read = posted + rejected every run, and signals the outcome for the CL to act on. Every I/O (e)-guarded. Reading the spec like a professional: nouns become files and DSs, verbs become procedures, rules become select/when, what-ifs become the error file. The transaction and error file DDS, the report layout, and a walking skeleton that runs clean end to end before any business logic. Layered validation as a procedure returning a reason code, driver-tested before it is wired in. Fees, the report and the error file side by side, with the reconciliation rule the program checks itself. Outcomes — clean, partial rejects, fatal — and the edge-case matrix: empty input, all rejects, a wrong override, an unsorted rate table. Then a line-by-line code review calling back every session, the coursework-versus-production diff, and sixty seconds of the COBOL capstone beside the RPG one — the same spec, two platforms. ORDPOST is the same business capstone as CS110 COBOL Programming I’s ACCTPOST, on purpose.
LAB Draw your own structure chart and file list from the spec. Build the skeleton — four files, batch-submitted via your CL — to a clean completion with no logic. Driver-test validateTran against the six-record set and its published reason codes. Complete both outputs over the 20-record test file; totals must reconcile and match the published values, three fees hand-verified to the penny. Run all five supplied test files and record outcome and behaviour in the test-log template — all five must match. Apply the self-review checklist, fix what it catches, and submit your final ORDPOST with its test log. Course complete.
CobolStack Certificate of Completion — RPG Programming I (CS210) is issued from the lab harness’s own record of your runs — not from attendance. To earn it you must clear every gate below:
The certificate attests that you can write production-shaped free-format RPG IV on IBM i — declare data correctly, compute exactly, control flow cleanly, read and change DB2 for i files with every I/O guarded, drive tables and procedures, and package a batch job behind a CL driver — and read the fixed-format code you will maintain: the RPG baseline that IBM i developer postings ask for, verified from your own programs.
Your seat is a private, full IBM i-compatible environment (SteelFrame X) with 5250 in the browser, PDM and SEU, CRTBNDRPG and CRTBNDCL, DB2 for i physical and logical files from DDS, DSPFFD and STRSQL, SBMJOB to QBATCH, spooled files and job logs in the browser — nothing to install, snapshot and reset per exercise. By the end of the course the lab harness will have verified: a compiled program for every hands-on exercise; eight session labs that each grow the last — the record layout, the pay calculator, the structured order processor, the complete report with its CL driver, the table-driven report and the shared-logic refactor; and the ORDPOST capstone, whose posting report, error file and outcome signal reconcile read = posted + rejected and match the published values on all five test files.