oberonc is a self-hosted Oberon-07 compiler targeting MS-DOS real-mode large memory
model (CS≠DS≠SS). It produces RDOFF2 object files and .om archive libraries, linked
into DOS MZ executables. The entire toolchain runs natively on MS-DOS and under the
xt emulator on Linux/macOS.
Self-hosting (2026-06-09): The compiler is written in Oberon and compiles itself.
boot/oc.exe (a checked-in MS-DOS binary) seeds the build. From there, the compiler
rebuilds itself and all tools from Oberon source. The self-hosting regression test
(tests/test_selfhost.sh) verifies boot/oc.exe → src/oc/*.Mod → oc1.exe and then
oc1.exe → oc2.exe are byte-identical.
- Full Oberon-07 subset with practical extensions (see "Language extensions" below).
- RDOFF2 code generation with smart linking — only reachable modules are emitted.
- x87 FPU support: REAL (32-bit) and LONGREAL (64-bit) arithmetic, comparison, conversion.
- LONGINT (32-bit signed integers) with helpers for multiplication, division, and modulus.
- SET type (16-bit): literals, ranges, set operators, IN membership test.
- Constant expression folding for CONST declarations, ARRAY dims, CASE labels.
- FAR/NEAR procedure calling conventions with procedural variables.
- Nested procedures (no uplevel access — inner procs see only globals, imports, own params).
- Dynamic allocation: NEW/DISPOSE with typed and sized variants; ADDRESS far pointers.
- Forward and self-referential POINTER TO RECORD types within a TYPE section.
- SYSTEM intrinsics: MOVE, FILL, ADR, SEG, OFS, PTR, LSL, LSR, ASR, ROR; PORTOUT/PORTIN.
- EXTERNAL procedure declarations (body provided by an external .rdf at link time).
$Ldirective to pack hand-assembled .rdf files into .om archives.$Mdirective to declare stack and heap sizes.$Rdirective to enable/disable array bounds checking.- Dead-code/unused-symbol warnings (non-fatal, stderr).
- All-in-one
oc.exe: dep-scan + incremental compile + smart link in one binary.
//single-line comments.INLINE(byte, ...)as a statement: emits raw bytes inside a regular procedure body.(*$L path.rdf*)///$L path.rdf— include extra .rdf in .om archive.(*$M stack, min, max*)— stack and heap size hints.(*$R+*)/(*$R-*)— enable/disable array bounds checks.FAR/NEARmodifiers on PROCEDURE declarations and types.EXTERNALmodifier on PROCEDURE declarations.VAR namewithout: type(typeless VAR parameter — callee receives ADDRESS).ADDRESSbuilt-in type (4-byte far pointer, any segment).FLOAT(x)synonym forREAL(x);ENTIER(x)synonym forFLOOR(x).ARRAY m, n OF Tmulti-dimensional array sugar (up to 7 dims).- Named integer constants as array dimensions.
NEW(p, n)sized allocation (n is a runtime byte-count expression).- Implicit INTEGER→REAL/LONGREAL coercion in binary expressions.
oberonc/
boot/ Bootstrap MS-DOS binaries (immutable — never modified by make)
oc.exe All-in-one compiler/linker/dep-scan
olib.exe Archive manager
src/ Oberon source for all tools
oc/ Compiler + linker (Main, Parser, Link, …)
olib/ Archive manager source
tools/ Test tools (rdfgrep.Mod)
src-lib/ Oberon library sources + SYSTEM assembly
lib/ Compiled library output (OBERON.OM after make)
tests/ Test suite (MANIFEST.TSV, T*.Mod, testall.Mod, …)
docs/ Grammar, ABI, build and test reference
CLAUDE.md Developer guide for Claude Code sessions
MANUAL.MD Programmer manual: dialect, ABI, calling conventions
| Module | Purpose |
|---|---|
| SYSTEM | Runtime helpers: alloc, halt, FPU check, INT calls |
| Out | Character, string, integer, hex output to stdout |
| Out87 | REAL / LONGREAL formatted output (needs FPU) |
| In | Stdin input (integers, strings) |
| Strings | Length, Pos, Append, Insert, Delete, Replace, Extract, Copy |
| Files | DOS file I/O (open, read, write, close, seek) |
| Crt | Terminal: cursor, clear, colour (DOS INT 10h) |
| Dos | DOS interface: args, Exec, ChDir, environment |
| IO | Raw console/file byte I/O (Rider wrapping DOS handle) |
| Mem | Heap allocator with 65000-byte limit guard |
| Math | 8087 math functions (sin, cos, sqrt, …) |
Requirements:
- GNU make
xtDOS emulator (required for all compilation — runs boot/oc.exe and bin/oc.exe)
Build:
make # boot/oc.exe → stdlib → bin/oc.exe → bin/olib.exe → tools → OBERON.OM
make test # full clean + rebuild + run 247 manifest tests (host-side, fast)
make testall # full DOS-side suite via xt: manifest + Section 17/18 (~9 min)Compile a module (via xt):
xt run --max=50000000 -c . bin/oc.exe -L lib Hello.ModCompile + link to executable:
xt run --max=50000000 -c . bin/oc.exe -L lib -entry Run Hello.Mod hello.exe
xt run --max=5000000 hello.exeUse on real MS-DOS:
SET OBERON_LIB=C:\lib
oc.exe Hello.Mod
oc.exe -entry Run Hello.Mod hello.exe
| Proc type | Epilogue | First param | Proc-var size |
|---|---|---|---|
| FAR (exported) | RETF | [BP+6] | 4 bytes |
| NEAR internal | RET | [BP+4] | 2 bytes |
VAR parameters pass a 4-byte far address; open-array formals use a 6-byte slot {offset, segment, LEN}.
DOS real-mode large model: CS≠DS≠SS. The linker places all modules' data in one
combined DS, code groups in their own CS paragraphs, and the stack in a separate SS.
SYSTEM.ADR returns a full far ADDRESS (segment:offset) for any variable form;
locals use SS, globals use DS.
247-row manifest test suite plus Section 17 executable tests and Section 18 unit tests.
| Suite | What it covers |
|---|---|
| MANIFEST.TSV (247) | Compile-output checks: codegen bytes, RDOFF structure, errors, errorlevel |
| Section 17 (15+) | Executable tests: types, control flow, procedures, records, pointers, SYSTEM |
| Section 18 (7) | Unit tests for compiler modules: Scan, Syms, Cgen, Rdoff, Tar, Def, Parser |
MANUAL.MD— programmer manual: dialect, ABI, calling conventions, open arraysdocs/oberon07.ebnf— authoritative grammardocs/oberon-language.md— type sizes, ABI, naming, FAR/NEAR, module initdocs/implementation-rules.md— DOS/portability rulesdocs/build.md— detailed build instructions and oc.exe usagedocs/tests.md— all test information: how to run, add, and interpret testsdocs/xt.md— xt emulator referencedocs/rdoff2-spec.md— RDOFF2 format specification
Public domain. See LICENSE.TXT.