Build MicroEMACS (torvalds/uemacs, the uEmacs/PK 4.0 line) with badc and drive the editor under a pseudo-terminal. The editor is a termios + termcap program: it puts the terminal into raw mode itself, reads keystrokes byte by byte, paints through termcap capabilities, and interprets its own startup-file language, so the smoke exercises a terminal program end to end rather than a batch one.
The source tree is not committed: setup.py fetches the pinned
commit from the kromych/badc vendor-deps release (the upstream GitHub
archive of commit 1c1b25e, mirrored as uemacs-20210330-1c1b25ef.tar.gz),
verifies a sha256, and extracts it under demos/uemacs/.cache/. The
tree is built as upstream ships it, with the Makefile’s own defines for
the host OS; no patches. While the release lacks the asset, setup.py
exits with status 3 and the smoke reports a skip naming it.
| File | Tracked? | Purpose |
|---|---|---|
setup.py |
yes | Fetch + extract the pinned commit. Idempotent. |
smoke.py |
yes | Build with badc and with the host cc, drive both under a pty, compare. |
.cache/ |
no | Cached archive and the extracted tree. |
The termcap declarations badc compiles tcap.c against are
demos/include/term.h and demos/include/curses.h; the implementation
is the system terminfo library (the SDK’s libcurses on macOS,
libtinfo on Linux).
python demos/uemacs/setup.py # fetches into demos/uemacs/.cache/
python demos/uemacs/smoke.py # builds + runs the editor at -O0 and -O
smoke.py returns 0 with smoke OK [badc-O0] / smoke OK [badc-O]
when every step passes, and 1 with a line naming the failed step
otherwise. It honours BADC=path/to/badc. --out <path> copies the
-O build of the editor to that path once every run has passed, so
python demos/uemacs/smoke.py --out ~/bin/em leaves a badc-built
MicroEMACS on your PATH.
SRC list with badc -c and
links em with badc’s linker against the system terminfo library, at
-O0 and at -O.cc as the reference.TERM=vt100, 24x80) in two scenarios,
each in a fresh directory holding a one-line scratch.txt:
em @start.rc, where the file is written in the
editor’s command language – find-file, end-of-file,
insert-string, newline, save-file, exit-emacs – so the
editor writes the file and exits before reaching its command loop.C-x C-s (save) and C-x C-c (exit)
are written to the pty once the editor has produced output, which
it does only after switching the terminal to raw mode.ubuntu-latest, ubuntu-24.04-arm, and macos-latest, from
.github/workflows/ci.yml. The terminal layer is POSIX-only upstream,
so the smoke prints a skip on Windows; the local-box roster lists the
demo for the POSIX lanes.
uemacs entry in scripts/vendor_deps/build_bundle.py
(commit, author date), run it, and upload the new asset to the
release as its output says.VERSION, UPSTREAM_SHA, and SHA256 in setup.py (and
UPSTREAM_SHA in smoke.py).python setup.py -v followed by python smoke.py.TODO: master at 325a8e97 (2026-08-06; mirrored as
uemacs-20260806-325a8e97.tar.gz) is not taken. It uses bool, true
and false as C23 keywords, without <stdbool.h>, which badc does not
accept, and it no longer builds on macOS: file.c reads st_mtim and
posix.c clears OLCUC and XCASE, none of which the macOS SDK has, so
Apple clang 21 fails both units even under -std=gnu23. Its Makefile
lists 28 units (ansi, crypt, ibmpc, pklock, termio, util,
vmsvt and vt52 are gone, spell is new) and compiles them with
-DPOSIX -D_GNU_SOURCE on every OS, plus pkg-config --cflags ncurses
(-D_DEFAULT_SOURCE -D_XOPEN_SOURCE=600 on Fedora) and -DHUNSPELL when
pkg-config finds hunspell, so the bump replaces UNITS and DEFINES in
smoke.py and makes the demo Linux-only.