Skip to content

vms-ec70: MMK.EXE native — MadGoat MMK parses descrip.mms + drives the toolchain (self-host spine #4) - #446

Merged
baron-3dl merged 2 commits into
mainfrom
vms-ec70-mmk-native
Aug 13, 2026
Merged

baron-3dl merged 2 commits into
mainfrom
vms-ec70-mmk-native

Conversation

@baron-3dl

Copy link
Copy Markdown
Contributor

Self-host spine #4 — MMK.EXE native image (bead vms-ec70)

Builds the vendored MadGoat MMK (tests/corpus/tier3-mmk/, third-party BSD freeware) as an OVMX-native image. MMK now actually parses a descrip.mms through the just-landed self-host stack and emits the correct build plan — the capstone before spine #5 (a real descrip.mms tree).

What MMK.EXE now does (proven end-to-end)

  • descrip.mms parse via the REAL lib$table_parse engine, driven by the vms-486 PARSE_TABLES.MAR→C grammar compiled -DOVMX_MMK_PRODUCTION so its transitions fire MMK's own parse_store/parse_obj_store (not the vms-486 test probe).
  • CLI$ compiled-CLD: mmk_cld.cld is compiled at run time by cli$compile_cld (vms-8c1) and driven by cli$dcl_parse/cli$present/cli$get_value.
  • build engine: MMK builds the target/dependency graph and, in /NOACTION, emits the resolved TCC/LINK commands in dependency order.

Clean-room build shim (Rule 8), tests/corpus/tier3-mmk/ovmx/

The 15 vendored make-engine TUs are stock except for tagged OVMX (vms-ec70) seams (109 inserts / 4 deletes across 9 files — grep the tag). The shim (ovmx_mmk_compat.h + 5 .c companions) adapts stock DEC-C VMS source to the OVMX RTL: VMS storage-class keywords; struct/constant spellings; a PP_NARG call-site macro replacing DEC C's va_count (no SysV x86-64 ABI equivalent); variadic wrappers for RTL arity differences.

Real RTL fixes landed alongside (VMS-faithful, benefit any caller)

  • tpadef.h/lib_tparse.c: add TPA$B_CHAR (matched char) — MMK needs it to accrete suffix rules.
  • lib_vm.c: honour LIB$M_VM_GET_FILL0 (zero returned blocks); add missing lib$reset_vm_zone; harden create_vm_zone optional-arg over-read (via MMK-side wrapper).
  • lib_output.c: lib$get_foreign now supports a dynamic (class D) descriptor (str$copy_dx) — MMK passes an INIT_DYNDESC, which previously returned empty.
  • rms/nam.h: add nam$b_nop/nam$l_rlf/nam$t_dvi + NAM$M_SYNCHK.

Test (CI-wired)

tests/toolchain/run_mmk_parse.sh + a CMake mmk_native target build MMK.EXE against the OVMX RTL and run it on a real descrip.mms; the test asserts MMK emits TCC MMKSPINE.C then LINK MMKSPINE.OBJ in dependency order, exit = SS$_NORMAL. Runs in the standard ctest as toolchain-mmk-parse.

  • toolchain-mmk-parse: PASS
  • Full suite: 167/167 passed, 0 failed (no regressions); vms-486 grammar test still green.

Native LINK.EXE/IMGACT packaging recipe provided: src/vmslink/mk_mmk.sh (mk_dcl.sh-style).

Deferred (flagged, NOT faked)

  • Actual command execution (turning the plan into a built+activated image) rides MMK's DCL-subprocess/mailbox/AST drive (build_target.c send_cmd_and_wait), which needs OVMX lib$spawn-of-DCL + mailboxes + write-attention ASTs. ovmx_mmk_sp.c supports /NOACTION honestly and returns an authentic error for real builds — no fake success (INV-6 / Rule 9).
  • .OLB module-date (lbr$) in get_rdt, CMS, and the compiled default-rules codegen tools (genstruc/mmk_compile_rules). MMK ships no built-in rules yet, so a descrip.mms must state rules explicitly.

🤖 Generated with Claude Code

alice and others added 2 commits August 13, 2026 05:14
…e toolchain (self-host spine #4)

Build the vendored MadGoat MMK (tests/corpus/tier3-mmk/) as an OVMX-native
image. MMK now REALLY parses a descrip.mms through the just-landed self-host
stack and emits the correct build plan:

  - CLI$ compiled-CLD: mmk_cld.cld is compiled at run time by cli$compile_cld
    (vms-8c1) and driven by cli$dcl_parse/present/get_value (ovmx_mmk_cld.c).
  - description-file parse: MMK's parse_descrip/parse_objects run the REAL
    lib$table_parse engine, driven by the vms-486 PARSE_TABLES.MAR->C grammar
    compiled -DOVMX_MMK_PRODUCTION so its transitions fire MMK's own
    parse_store / parse_obj_store (not the vms-486 test probe).
  - build engine: MMK builds the target/dependency graph and, in /NOACTION,
    emits the resolved TCC/LINK commands in dependency order.

The 15 vendored make-engine TUs are stock except for tagged "OVMX (vms-ec70)"
seams (grep the tag). A clean-room (Rule 8) build shim in
tests/corpus/tier3-mmk/ovmx/ adapts the stock source to the OVMX RTL:
  - ovmx_mmk_compat.h  VMS storage-class keywords; struct/constant spellings;
                       a PP_NARG call-site macro replacing DEC C's va_count
                       (no SysV x86-64 ABI equivalent); variadic wrappers for
                       RTL arity differences (sys$parse/search/filescan,
                       ots$cvt_tu_l, str$position, lib$get[_symbol]/set_logical,
                       lib$create_vm_zone).
  - ovmx_mmk_{cld,sp,cms,builtins,compat}.c companions.

Real RTL fixes landed alongside (all VMS-faithful, benefit any caller):
  - tpadef.h/lib_tparse.c: add TPA$B_CHAR (matched char) — MMK needs it to
    accrete suffix rules.
  - lib_vm.c: honour LIB$M_VM_GET_FILL0 (zero returned blocks) — MMK's zones
    rely on it; add lib$reset_vm_zone (was missing).
  - lib_output.c: lib$get_foreign now supports a dynamic (class D) descriptor
    (str$copy_dx) — MMK passes an INIT_DYNDESC, which previously returned empty.
  - rms/nam.h: add nam$b_nop/nam$l_rlf/nam$t_dvi + NAM$M_SYNCHK.
  - lib_vm.c create_vm_zone over-read hardened via the MMK-side wrapper.

Test (CI-wired): tests/toolchain/run_mmk_parse.sh + a CMake mmk_native target
build MMK.EXE against the OVMX RTL and run it on a real descrip.mms; the test
asserts MMK emits `TCC` then `LINK` in dependency order (exit = SS$_NORMAL).
Passes in the standard ctest (toolchain-mmk-parse). Full suite: 167/167 green,
no regressions; vms-486 grammar test still green.

Native LINK.EXE/IMGACT packaging recipe: src/vmslink/mk_mmk.sh (mk_dcl.sh-style).

DEFERRED (flagged, not faked): actual command EXECUTION (turning the plan into
a built+activated image) rides MMK's DCL-subprocess/mailbox/AST drive
(build_target.c send_cmd_and_wait), which needs OVMX lib$spawn-of-DCL +
mailboxes + write-attention ASTs; ovmx_mmk_sp.c supports /NOACTION honestly and
returns an authentic error for real builds (no fake success). Also deferred:
.OLB module-date (lbr$) in get_rdt, CMS, and the compiled default-rules codegen
tools (genstruc/mmk_compile_rules) — MMK ships no built-in rules yet, so a
descrip.mms must state rules explicitly.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…embed generator

Rebased onto current origin/main (picks up the vms-bd1 frozen shareable-vector
mechanism, which post-dated the original base). Two CI-red root causes fixed:

1. Native-link graph (LINK.EXE Graph / DCL native / LIBRARIAN / IMGACT / self-
   link, all RED): the new lib$reset_vm_zone was an UNFROZEN universal, so
   mk_libvms_shr.sh appended it and invoked `join` — absent from the alpine musl
   container (no coreutils) → Error 127, failing every job that rebuilds
   LIBVMS$SHR. Fix: append lib$reset_vm_zone=PROCEDURE to the END of
   libvms_shr.vec and libvms_shr.vec.frozen (append-only; existing indices/
   GSMATCH unaffected). Verified in-container: "351 frozen + 0 appended", join
   skipped, link_native_graph produces 9 EM_X86_64 artifacts, zero DT_NEEDED.

2. Build & Test / Static Analysis / Conformance / Corpus (all RED building
   mmk_native): the CLD-embed generator was gen_mmk_cld_src.cmake, but
   .gitignore excludes *.cmake, so it never landed in a clean checkout ("No rule
   to make target gen_mmk_cld_src.cmake"). Fix: ship it as gen_mmk_cld_src.sh
   (not ignored) and invoke it from the custom command.

Full ctest: 170/170 (was 167; main added 3). toolchain-mmk-parse + symvec-freeze
green. No regressions from the rebase.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@baron-3dl
baron-3dl force-pushed the vms-ec70-mmk-native branch from 4ed8e97 to 258e877 Compare August 13, 2026 05:20
@baron-3dl
baron-3dl merged commit c2d25b2 into main Aug 13, 2026
61 checks passed
baron-3dl added a commit that referenced this pull request Aug 13, 2026
…456)

Bump OVMX_PRODUCT_VERSION V0.4-1 → V0.4-2. 10 PRs since V0.4-1, toward the
0.5 milestone:

  owns-kernel    #450 OVMX builds its own pinned linux-6.12.103 LTS from source
                 (byte-reproducible, boots 17/17+24/24) — vms-19e beachhead
  self-host #4   #446 MMK.EXE parses descrip.mms + emits TCC→LINK plan
                 (exec-drive facilities, all proven vs real /dev/vms:)
                 #451 lib$spawn real DCL (facade killed) · #452 mailbox IPC
                 #453 write-attention AST · #454 exec-drive design record
  UX fidelity    #447 DIRECTORY format+versions · #448 Ctrl-T status line
                 #449 hierarchical HELP engine · #455 SHOW MEMORY (drop
                 buffers+cached fabrication)
  + swept other threads' merged work

MMK does not yet DRIVE builds (spine #4 needs async AST delivery + IO$M_NOW
+ DCL-mailbox-SYS$INPUT — filed vms-feb/5df/786, faithful path in flight).

Co-authored-by: alice <alice@workspace.local>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
baron-3dl added a commit that referenced this pull request Aug 13, 2026
mk_libvms_shr.sh computed the newly-discovered-universals append set with
`join -t= append.names disc.vec`. `join` is a coreutils tool ABSENT from the
alpine-musl native-link container (busybox) -> Error 127 broke every job that
rebuilds LIBVMS$SHR the moment the append set was non-empty. The vms-bd1 freeze
left it latent (all symbols frozen => empty append => the join line short-
circuited on `[ -s append.names ]`); the next newly-exported libvms universal
re-triggered it (vms-ec70 #446, vms-feb #457).

Replace the join with awk set-membership: emit each discovered `name=class`
whose name is in the append set, iterating disc.vec (which is `sort -u`'d, so
name-sorted, names unique) -> byte-identical to join's sorted-by-key output.
comm and paste stay (busybox HAS both; verified against alpine:3.20).

Proof: alpine:3.20/amd64 `cmake --build --target link_native_graph` with the
last universal temporarily unfrozen (350 frozen + 1 appended, NON-EMPTY append
set) links the full graph clean (BUILD_RC=0) through LOGINOUT.EXE, with the
"appended BEYOND the frozen manifest" note firing. join/awk equivalence checked
on host for both empty and non-empty append sets. Freeze gate + negctl green.

Co-authored-by: alice <alice@workspace.local>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant