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

Eric Streit 5a2c27d1f6 compiler: zero AH for one-byte FOR control variables há 1 dia atrás
Resources 1adc41da2d TP3-comp: working TP3.0 shell in GNU Modula-2 (-fiso) há 1 mês atrás
calc-port 5b8e928c6c Analysis: porting CALC.PAS to GNU Modula-2, with the measurements kept há 3 semanas atrás
shell df803160d0 compiler: zero AH for one-byte FOR control variables há 1 dia atrás
.gitignore 35d5012135 editor: the command keys from a text file (TP3.KEY) há 1 semana atrás
CALC-COMPILE.md df803160d0 compiler: zero AH for one-byte FOR control variables há 1 dia atrás
CALC-PORT.md 5b8e928c6c Analysis: porting CALC.PAS to GNU Modula-2, with the measurements kept há 3 semanas atrás
FREEDOS-CALC.md cf318904bb runtime: put DOS output characters in DL há 1 dia atrás
README.md df803160d0 compiler: zero AH for one-byte FOR control variables há 1 dia atrás
RESUME-TP3.md 1adc41da2d TP3-comp: working TP3.0 shell in GNU Modula-2 (-fiso) há 1 mês atrás
SUMMARY.md df803160d0 compiler: zero AH for one-byte FOR control variables há 1 dia atrás
TERMINAL.md 35d5012135 editor: the command keys from a text file (TP3.KEY) há 1 semana atrás
TP3-COMPILER.md 1bed3bbc1c compiler: string concatenation, a + b há 1 semana atrás
TP3-EDITOR-PSEUDOCODE.md 9088d9ebf2 TP3-comp: shell + Compiler.mod build clean under gm2 -fiso -Wall há 1 mês atrás
TP3-EDITOR.md c342d7cae3 TP3-comp: document how the original TP3 editor works há 1 mês atrás
v-TP3-8086-LOWERING.md 711a1219d6 Add the v-TP3-8086-LOWERING milestone summary, and move the tag onto it há 3 semanas atrás
v-TP3-DEAD-FIXTURES.md edd057f5ce TP3-ARGORDER: push each argument as it is parsed, and read the frame from BP+4 backwards há 2 semanas atrás
v-TP3-DECL-WINDOW-STRIDX.md 632cef7646 docs: session summary and resume point (declarations, code window, string subscripts) há 1 semana atrás
v-TP3-INTERRUPT-RESTORE.md 2ae00d1c98 tests: session summary for the nonvacuity interrupt-restore work há 1 semana atrás
v-TP3-STRCAT.md 1bed3bbc1c compiler: string concatenation, a + b há 1 semana atrás
v-TP3-STRCMP.md b58b3deaef compiler: string comparison, = <> < <= > >= há 1 semana atrás
v-TP3-STRIDX-VAR.md baf4bcdf99 compiler: variable string subscripts, s[i] with a run-time index há 1 semana atrás

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-CALC-CHARFOR:

  • 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 under qemu-system-i386 and Exec86.
  • CALC.PAS compiles and runs. The generated CALC.COM reaches the welcome screen, grid and command menu, accepts a numeric formula or text cell, and exits cleanly through /Q.
  • 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 under the test harness or the CALC launcher below.
  • The next capacity limit is CALC's full Help/heap use (16,281-byte Pages plus a 16 KiB stack); the current flat-segment layout has less headroom than that. SUMMARY.md and CALC-COMPILE.md record the details.

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.

CALC launcher

tests/calc_cli.py builds CALC.COM in a temporary include directory, boots it under qemu and prints its serial output:

cd shell
python3 tests/calc_cli.py                  # build + default welcome/quit keys
python3 tests/calc_cli.py --com CALC.PAS.COM --keys '\r\r/Q'
python3 tests/calc_cli.py --keys-file keys.bin --raw > screen.bin

Options: --keys (Python escapes such as \r, \n, \x1b), --keys-file, --com, --timeout, --raw, --quiet, --verbose, and --no-keypress (make AH=0Bh report no queued key; useful for scripted CALC input). Input is a static boot-time key stream, not a live terminal. The automated smoke check is python3 tests/calc_smoke.py, run by tests/run_all.sh. For a manual FreeDOS/qemu setup, see FREEDOS-CALC.md; CALC is verified under the FreeDOS 1.4 LiveCD.

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.