Turbo-pascal 3 recreation, based on multiple disassembiles and Collibri Books.

Eric Streit edd057f5ce TP3-ARGORDER: push each argument as it is parsed, and read the frame from BP+4 backwards 2 روز پیش
Resources 1adc41da2d TP3-comp: working TP3.0 shell in GNU Modula-2 (-fiso) 2 هفته پیش
calc-port 5b8e928c6c Analysis: porting CALC.PAS to GNU Modula-2, with the measurements kept 5 روز پیش
shell edd057f5ce TP3-ARGORDER: push each argument as it is parsed, and read the frame from BP+4 backwards 2 روز پیش
.gitignore 842dcff3a8 TP3-CMDRUN: the R key runs the image in-process, with a second oracle 3 روز پیش
CALC-PORT.md 5b8e928c6c Analysis: porting CALC.PAS to GNU Modula-2, with the measurements kept 5 روز پیش
README.md 586ff4aa09 Make the emitted code 8086 code, and prove it can go red 5 روز پیش
RESUME-TP3.md 1adc41da2d TP3-comp: working TP3.0 shell in GNU Modula-2 (-fiso) 2 هفته پیش
SUMMARY.md edd057f5ce TP3-ARGORDER: push each argument as it is parsed, and read the frame from BP+4 backwards 2 روز پیش
TP3-COMPILER.md 586ff4aa09 Make the emitted code 8086 code, and prove it can go red 5 روز پیش
TP3-EDITOR-PSEUDOCODE.md 9088d9ebf2 TP3-comp: shell + Compiler.mod build clean under gm2 -fiso -Wall 2 هفته پیش
TP3-EDITOR.md c342d7cae3 TP3-comp: document how the original TP3 editor works 2 هفته پیش
v-TP3-8086-LOWERING.md 711a1219d6 Add the v-TP3-8086-LOWERING milestone summary, and move the tag onto it 5 روز پیش
v-TP3-DEAD-FIXTURES.md edd057f5ce TP3-ARGORDER: push each argument as it is parsed, and read the frame from BP+4 backwards 2 روز پیش

README.md

TP3-comp

Recreating Turbo Pascal 3.0 (shell, editor, compiler, interpreter) in GNU Modula-2 (-fiso). Faithful to the original: the screen layout, keys and behaviours are reconstructed from the disassembled TP3.0 source (Resources/) and the reference manual.

State

Where things are: SUMMARY.md. It holds the milestone table, the list of checks and what each one cannot see, and the numbers behind every claim.

There used to be a milestone table here as well, and it drifted six milestones behind while still reading as authoritative: it said "no compiled program has been executed yet" and "CmdRun is a stub and the runtime blob does not exist" through five tagged milestones in which those three things all became true. A second copy of a status table is a claim about the world that expires silently and is never noticed expiring, so there is one now, and this file says where it is.

In short, current as of v-TP3-DEAD-FIXTURES:

  • The shell and the WordStar-style editor are done.
  • The compiler front end and 8086 code generator are done for the language subset the fixtures cover, and the emitted .COM images run: 31 fixtures boot in qemu-system-i386 and print exactly their expected bytes, and 36 further cases call the runtime's own entries directly.
  • The shell's R key is still a stub. There is no in-process 8086 interpreter, so nothing runs a .COM from inside tpshell itself; execution happens only under the test harness.
  • string variables, nested procedures, var parameters, range and index checks, typed constants and array at its point of use are not implemented. SUMMARY.md lists them with the reason for each.

Build

Requires GNU Modula-2 (gm2, tested with 16.0.1) and a C compiler for the FOR "C" bridge.

cd shell
make
./tpshell

The shell runs in raw mode: it needs a real ANSI terminal, no wrappers.

To run the checks: cd shell && bash tests/run_all.sh. It is not part of make, because it needs qemu and takes a few minutes.

Layout

  • shell/Term.def|mod — raw termios keyboard + ANSI screen primitives (blocking GetCh, non-blocking Avail/GetKey via poll, GotoXY, highlight Marked/Normal, Beep).
  • shell/Posix.def|Posix.c — DEFINITION MODULE FOR "C" bridge to libc: read/write/open/close/unlink/rename/getcwd/chdir/opendir/readdir/closedir/ statvfs/poll and termios (tcgetattr/tcsetattr/cfmakeraw).
  • shell/TextBuf.def|mod — the shared TP3-style text buffer: a 62903-char array, lines terminated by CR. Text is kept in memory so the editor and the shell's S (save) operate on the same buffer.
  • shell/Editor.def|mod — WordStar-style full-screen editor.
  • shell/Shell.mod — TP3.0 main-menu dispatcher (kmenu/kcmdtab), work-file load/save with .BAK rotation, directory listing, options menu.
  • shell/Compiler.def|mod — lexer, parser, symbol table and the 8086 code generator. Compiler.CodeByteAt exists so a test can read the emitted image.
  • shell/Runtime.def|mod — the 8086 runtime library, built as a byte blob at run time and copied to the front of every image. Its entries are addressed by name from Runtime.def; the emitter procedures are audited name-against-decode.
  • shell/Linker.def|mod — assembles [JMP rel16][runtime][header][program] and writes a real DOS .COM when the Destination option is COM.
  • shell/Makefile — the authoritative build recipe; two-phase link, see SUMMARY.md.
  • shell/tests/ — the harnesses. run_all.sh runs them, nonvacuity.sh proves each one can go red. tests/fixtures/expected.tsv is the live fixture matrix and is asserted against, not copied into prose.
  • SUMMARY.md — the state document: milestones, checks, numbers, and what is still missing.
  • TP3-COMPILER.md — how the compiler works, the build recipe, and the codegen bug classes with their fixes.
  • TP3-EDITOR.md — the editor's key handling and screen layout.
  • RESUME-TP3.md — book-derived reference for the 8086 code the TP3 compiler generates (source of the compiler phase).
  • Resources/ — OCR of "Au coeur de Turbo Pascal", TP3.0 manual and the disassembled TPSRC1-10. The disassembly is the ground truth: when our behaviour and the book disagree, the disassembly wins.

Shell (TP3.0 main menu)

Exact TP3.0 screen: Logged drive, Active directory, Work file, Main file, Edit Compile Run Save / Dir Quit compiler Options, Text: n bytes, Free: n bytes, > prompt. Command letters are drawn bold (TP3 uses high-bit characters).

Key Action
L new drive / directory
A new active directory
W set work file (auto-.PAS), Loading/New File
M set main file
E edit work file
C compile (wired: TP3 error report + editor jumps to the error)
R run — stub, prints Interpreter pending - compiled code is in memory
S save with ^Z EOF; old version → .BAK
D directory listing, DOS *.* mask, k bytes free
O options submenu (compile target, Code/Data/Stack, params)
Q quit (prompts to save when text changed)

Any other key redraws the menu, like TP3.

Editor

WordStar-style full-screen editing over TextBuf. Status line: Line n Col n Insert/Overwrite Indent X:FILENAME. Text rows are screen rows 2–24; row 1 carries status/prompt/messages.

Highlights:

  • Movement — ^S/^D/^E/^X/^A/^F/^R/^C/^W/^Z and ^Q S/D/E/X/R/C/B/K/P, arrow keys / PgUp / PgDn / Home / End (ANSI escape sequences).
  • Editing — insert/overwrite (^V), ^G delete char, backspace joins lines, ^T word, ^Y line, ^Q-Y to end of line, ^N / CR line break, TAB auto-indent to word start on the line above.
  • Block — ^K B/K mark, ^K T word, ^K H show/hide, ^K C/V/Y copy/move/delete, ^K R/W read/write block to/from a file.
  • Search — ^Q-F find, ^Q-A replace, ^L repeat last; options B/G/n/U/W, and N (no-confirm) for replace; ^A matches any char, CR LF searches a line break.
  • ^P prefix inserts a literal control character; ^U / ESC abort prompts.
  • ^K-D returns to the shell; the text stays in memory, changed is reported and S (or the quit prompt) writes it to disk.

Disk format matches TP3: CRLF line endings and a trailing ^Z; load normalizes CRLF/LF, save re-expands.

Porting notes (gm2)

  • Foreign modules (DEFINITION MODULE FOR "C") must use ADDRESS, not Modula-2 record/pointer types — cast at the call site.
  • gm2 ICEs on FOR ... EXIT; use WHILE+flag (or LOOP+EXIT).
  • gm2 only emits main when the program module source is on the link line: gm2 -fiso -o tpshell Shell.mod Term.o Posix.o TextBuf.o Editor.o.
  • termios is used in raw mode, so every newline is explicit CR LF.
  • EXIT is only legal inside LOOP (ISO Modula-2), not WHILE.