Просмотр исходного кода

docs: document CALC launcher; add no-keypress boot mode

Eric Streit 3 дней назад
Родитель
Сommit
a6e27dc887
4 измененных файлов с 42 добавлено и 10 удалено
  1. 27 8
      README.md
  2. 3 1
      shell/tests/calc_cli.py
  3. 9 0
      shell/tests/exec/bootcom.s
  4. 3 1
      shell/tests/run_com_exec.py

+ 27 - 8
README.md

@@ -18,19 +18,20 @@ 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
 and is never noticed expiring, so there is one now, and this file says where it
 is.
 is.
 
 
-In short, current as of `v-TP3-DEAD-FIXTURES`:
+In short, current as of `v-TP3-CALC-CLI`:
 
 
 - The shell and the WordStar-style editor are done.
 - The shell and the WordStar-style editor are done.
 - The compiler front end and 8086 code generator are done for the language
 - 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.
+  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, and exits cleanly through `/Q`.
 - **The shell's `R` key is still a stub.** There is no in-process 8086
 - **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
   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.
+  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
 ## Build
 
 
@@ -48,6 +49,24 @@ 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
 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.
 `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:
+
+```sh
+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`.
+
 ## Layout
 ## Layout
 
 
 - `shell/Term.def|mod` — raw termios keyboard + ANSI screen primitives
 - `shell/Term.def|mod` — raw termios keyboard + ANSI screen primitives

+ 3 - 1
shell/tests/calc_cli.py

@@ -67,6 +67,8 @@ def main(argv=None):
                     help="only print the exit status")
                     help="only print the exit status")
     ap.add_argument("--verbose", action="store_true",
     ap.add_argument("--verbose", action="store_true",
                     help="show the compiler output and image size")
                     help="show the compiler output and image size")
+    ap.add_argument("--no-keypress", action="store_true",
+                    help="make AH=0Bh report no queued key (needed for scripted CALC input)")
     args = ap.parse_args(argv)
     args = ap.parse_args(argv)
 
 
     td = None
     td = None
@@ -80,7 +82,7 @@ def main(argv=None):
                      % (len(com), r.COM_MAX))
                      % (len(com), r.COM_MAX))
         keys = (open(args.keys_file, "rb").read()
         keys = (open(args.keys_file, "rb").read()
                 if args.keys_file else decode_keys(args.keys))
                 if args.keys_file else decode_keys(args.keys))
-        boot = r.build_boot_sector()
+        boot = r.build_boot_sector(no_keypress=args.no_keypress)
         with tempfile.TemporaryDirectory(prefix="tpcalc-run-") as runtd:
         with tempfile.TemporaryDirectory(prefix="tpcalc-run-") as runtd:
             img = os.path.join(runtd, "calc.img")
             img = os.path.join(runtd, "calc.img")
             open(img, "wb").write(r.build_floppy(boot, com, keys))
             open(img, "wb").write(r.build_floppy(boot, com, keys))

+ 9 - 0
shell/tests/exec/bootcom.s

@@ -272,6 +272,14 @@ handler:
 	jmp	.Ldone8
 	jmp	.Ldone8
 
 
 .Lh0b:					# input status: AL=FFh if a character waits
 .Lh0b:					# input status: AL=FFh if a character waits
+.ifdef NO_KEYPRESS
+	# CALC's main loop treats every queued byte after a Read as an extended
+	# key scan code.  A preloaded key stream therefore cannot drive it unless
+	# this status call reports "nothing waiting"; the CLI uses this build.
+	xorw	%ax, %ax
+	clc
+	jmp	.Ldone8
+.else
 	movw	INLEN, %ax
 	movw	INLEN, %ax
 	movw	INCUR, %bx
 	movw	INCUR, %bx
 	cmpw	%ax, %bx		# INCUR vs INLEN: >= is end of input
 	cmpw	%ax, %bx		# INCUR vs INLEN: >= is end of input
@@ -283,6 +291,7 @@ handler:
 	xorw	%ax, %ax		# AL = 0: nothing waiting
 	xorw	%ax, %ax		# AL = 0: nothing waiting
 	clc
 	clc
 	jmp	.Ldone8
 	jmp	.Ldone8
+.endif
 
 
 .Lh3d:					# open file: no filesystem in this harness
 .Lh3d:					# open file: no filesystem in this harness
 	# The runtime uses real DOS AH=3Dh.  A boot floppy has no DOS and no
 	# The runtime uses real DOS AH=3Dh.  A boot floppy has no DOS and no

+ 3 - 1
shell/tests/run_com_exec.py

@@ -90,7 +90,7 @@ if FLAT_LOAD + COM_MAX > INLEN_FLAT:
 EXIT_BASE = 1
 EXIT_BASE = 1
 
 
 
 
-def build_boot_sector(load_seg=None, inlen=None, copy_bytes=None, scratch=None):
+def build_boot_sector(load_seg=None, inlen=None, copy_bytes=None, scratch=None, no_keypress=False):
     """Assemble tests/exec/bootcom.s and return its 512 bytes."""
     """Assemble tests/exec/bootcom.s and return its 512 bytes."""
     with tempfile.TemporaryDirectory() as td:
     with tempfile.TemporaryDirectory() as td:
         obj, raw = os.path.join(td, "b.o"), os.path.join(td, "b.bin")
         obj, raw = os.path.join(td, "b.o"), os.path.join(td, "b.bin")
@@ -103,6 +103,8 @@ def build_boot_sector(load_seg=None, inlen=None, copy_bytes=None, scratch=None):
             cmd += ["--defsym", "COPY_BYTES=%d" % copy_bytes]
             cmd += ["--defsym", "COPY_BYTES=%d" % copy_bytes]
         if scratch is not None:
         if scratch is not None:
             cmd += ["--defsym", "SCRATCH_SEG=%d" % scratch]
             cmd += ["--defsym", "SCRATCH_SEG=%d" % scratch]
+        if no_keypress:
+            cmd += ["--defsym", "NO_KEYPRESS=1"]
         cmd += ["-o", obj, os.path.join(HERE, "exec", "bootcom.s")]
         cmd += ["-o", obj, os.path.join(HERE, "exec", "bootcom.s")]
         r = subprocess.run(cmd, capture_output=True)
         r = subprocess.run(cmd, capture_output=True)
         if r.returncode != 0:
         if r.returncode != 0: