Skip to content

ironwork 0.3.0

Choose a tag to compare

@github-actions github-actions released this 02 Oct 14:30
· 284 commits to main since this release

Summary

Every program of the 3,000-program census that is valid Enterprise COBOL 6.4 now compiles, and IBM’s run-time checks work.

  • Compiles: EXTERNAL and GLOBAL records and files, and USE GLOBAL; the REPLACE statement; items after an OCCURS DEPENDING ON table; INITIALIZE WITH FILLER, TO VALUE, REPLACING and DEFAULT; SET TO ENTRY; CURRENCY SIGN X'hh'; ALPHABETIC-UPPER and -LOWER, NX and floating-point VALUE literals; ASSIGN’s later names, PASSWORD and FUNCTION ALL INTRINSIC.
  • Checks: NUMCHECK and ZONECHECK test the zoned, packed and binary senders a statement reads; PARMCHECK catches a CALL that writes past WORKING-STORAGE; INITCHECK warns of an item used before any path sets it.
  • Runs: EXEC CICS HANDLE ABEND PROGRAM, LABEL, CANCEL and RESET; lp and lpr print on DD PRINTER; ironwork job passes PARM to a COBOL program and runs DFSORT’s INCLUDE, OMIT, INREC, OUTREC and OUTFIL; a MOVE of a zoned or packed sender holding a non-digit no longer abends at the MOVE.
  • Evidence: ironwork fuzz keeps each abend a generated input causes, with its smallest input, journal and coverage; --trace-statements records the statements a run starts.
  • VM: ironwork run --vm runs a lowered program’s core statements on the VM, and every test program that lowers runs on both executors.

Limit: the VM stops a run at file I/O, SORT, Report Writer, EXEC CICS and SQL, JSON and XML, Language Environment services and object-oriented COBOL, and the interpreter stays the default.

What 0.3.0 adds over 0.2.0

  • Language: EXTERNAL records and files belong to the run unit, and a program's GLOBAL records and files reach the programs it contains (C180, C181); USE GLOBAL serves a contained program's files. The REPLACE statement works on the text COPY has expanded (C160). An item after an OCCURS DEPENDING ON table is placed by the table's current count (C161). INITIALIZE takes WITH FILLER, TO VALUE, REPLACING and TO DEFAULT (C171). SET a procedure-pointer or function-pointer TO ENTRY, and CALL through it (C140). CURRENCY SIGN IS X'hh' through the program's code page (C141). IS ALPHABETIC-LOWER and -UPPER, NX literals, a floating-point VALUE on COMP-1 and COMP-2, and LENGTH OF a table element without subscripts (C172). ASSIGN's later names, PASSWORD in a SELECT, IS before an abbreviated relation's operator, and REPOSITORY's FUNCTION ALL INTRINSIC. Procedure-names of digits alone start their paragraph in Area A. WHENEVER, HANDLE and USE FOR DEBUGGING labels resolve in their own section (C151).
  • IBM's checking options: NUMCHECK, ZONECHECK, PARMCHECK and INITCHECK are read from a CBL or PROCESS card and encoded in the load module. NUMCHECK and ZONECHECK test each sender, and report under MSG or end the run with U4038 under ABD (C228, C229); ZON(LAX) tolerates the redefinitions IBM's examples show (C280), and invalid data no statement changes is reported at compile time (C281). PARMCHECK fills a buffer after WORKING-STORAGE before each CALL and checks it after (C226, C227). INITCHECK warns of an item used before any path sets it, IBM's message 7311 at W (C224, C225).
  • Run-time behaviour: EXEC CICS HANDLE ABEND PROGRAM, LABEL, CANCEL and RESET per logical level (C142). A MOVE of a zoned or packed sender copies its digits unchecked, as IBM's byte copy, PACK and UNPK do; the data exception comes from the arithmetic that next reads it (C240, C260). INITIAL programs, variable-length records and RECORD VARYING DEPENDING ON follow the Language Reference. XML PARSE, JSON GENERATE and JSON PARSE match IBM on segments, nulls and exceptions; CANCEL acts only on a dynamically called or contained program. A virtual printer: a CALL of SYSTEM with an lp or lpr command appends its files to DD PRINTER.
  • Jobs: ironwork job passes PARM to a COBOL program (C250, C251), runs DFSORT's INCLUDE, OMIT, INREC, OUTREC and OUTFIL, and reads JCL it refused before, NOTIFY=&SYSUID among it.
  • Evidence for cobolwork: ironwork fuzz runs a batch program on generated input and keeps each abend once by code and place, with its smallest input, journal and coverage, in the directory cobolwork's abend set reads. --trace-statements records each start of the statements a file lists.
  • Code generation: SORT, MERGE, RELEASE, RETURN, the Report Writer and INSPECT of a function result lower to the LIR. ironwork run --vm runs a lowered program's core statements on the VM, and the test harness runs every program that lowers on both executors and compares them. Lowering refuses NUMCHECK, ZONECHECK and PARMCHECK programs and EXTERNAL and GLOBAL storage.
  • Tools: tools/nist.py runs NIST CCVS85 as EXEC85 prepares it.

Census

On the 3,000-program sample of 3185RecentCobolRepos (seed 1) at 374fc2c, 1,236 programs compile, against 1,210 at 25befea before 0.2.0's cut. Each program still refused that was judged IBM-valid on 2026-10-01 was judged again from its new first error against IBM's Enterprise COBOL 6.4 documentation: none is valid Enterprise COBOL 6.4 except three uncertain ones with a doubled separator period. That gives 100% of the IBM-valid programs, or 99.8% counting the three. One program a 0.2.0 binary accepted is now refused, an ISO negative test with an EXTERNAL file's FILLER record, as the standard requires. No IBM compiler has checked these verdicts.

Known issue

0.3.0 cannot read a load module written by 0.2.0. Both versions write module format 0.1, but 0.3.0 added the NUMCHECK, PARMCHECK and INITCHECK settings to a module, and changed its LIR and DEBUG sections, without raising the format version. ironwork dump therefore refuses every 0.2.0 module with "OPTIONS is malformed" instead of a version message. Nothing in 0.3.0 runs a load module, so no run reads a 0.2.0 module wrongly. Compile the source again with 0.3.0's ironwork compile.

Install

ironwork for COBOL 0.3.0. Builds for Linux (static), macOS and Windows, and the npm package @portll/ironwork. The ironwork-tls archives are the same builds with TLS for --sql-db (rustls, sslmode=verify-full). The Python package is on PyPI as ironwork, and the crates are on crates.io. Each file carries SLSA build provenance: gh attestation verify -R Portll/ironwork.