• src/conio/cterm_atascii.c cterm_atascii.h cterm_cterm.c cterm_cterm.h

    From Deucе@VERT to Git commit to main/sbbs/master on Sun Apr 19 01:13:13 2026
    https://gitlab.synchro.net/main/sbbs/-/commit/7460ccb38cc178d2e99bc252
    Added Files:
    src/conio/cterm_atascii.c cterm_atascii.h cterm_cterm.c cterm_cterm.h cterm_dec.c cterm_dec.h cterm_ecma48.c cterm_ecma48.h cterm_internal.h cterm_petscii.c cterm_petscii.h cterm_prestel.c cterm_prestel.h cterm_vt52.c cterm_vt52.h
    Modified Files:
    src/conio/CMakeLists.txt cterm.c cterm.h cterm_test.c objects.mk
    Log Message:
    cterm: refactor to table-driven dispatch

    Step one in properly modular emulation.

    Replace the 2565-line do_ansi() switch with bsearch-based dispatch
    tables keyed by a 21-bit (intro | final | priv | interm) sequence
    key, and split the 7988-line cterm.c across per-standard files:

    cterm_ecma48.c ECMA-48 CSI/C1 handlers
    cterm_dec.c DEC private extensions (DECSM, DECRQM, DECCARA, ...)
    cterm_cterm.c SyncTERM/CTerm/XTerm extensions (incl. SCOSC/DECSLRM
    dispatcher, ANSI-music vs DL, CTerm RGB palette)
    cterm_vt52.c VT52 / Atari ST VT52
    cterm_atascii.c Atari 8-bit ATASCII
    cterm_petscii.c Commodore C64/C128 PETSCII
    cterm_prestel.c Prestel / BEEB serial attrs, VDU 23/28, prog memory

    The parser is now an incremental seq_feed() state machine that drops
    the legacy three-pass legal_sequence / parse_sequence / parse_parameters pipeline and the heap-allocated struct esc_seq it populated. SGR and
    DECCARA read cterm->seq_param_int[] / seq_param_strs[] directly.

    cterm_write's byte loop is reduced to the canonical two-check form (pick_accumulator -> dispatch); every emulation installs its own cterm->dispatch pointer at cterm_init time.

    Per-emulation dispatch wiring:

    * ANSI-BBS and Atari ST VT52 share cterm_accumulate_ecma_seq and
    seq_feed, each installing its own sorted dispatch table
    (cterm_ansi_dispatch[], cterm_st_vt52_dispatch[]) for bsearch.
    VT52 has its own single-byte dispatcher (cterm_dispatch_vt52)
    for VT52-specific C0 semantics (VT/FF as LF, bytes 1-6/14-31
    silently dropped) while sharing the sequence-parsing path.
    * PETSCII and ATASCII use a shared cterm_dispatch_byte with a
    256-bit per-emulation ctrl_bitmap[32] marking control bytes and
    a byte_handlers[256] table of per-byte handlers. Printable
    bytes go through cterm_c64_get_attr. ATASCII's one-shot ESC
    inverse installs cterm->accumulator (file-local
    atascii_literal_byte) which takes priority in
    cterm_pick_accumulator.
    * Prestel keeps its custom programmable-memory state machine
    (cterm_accumulate_prestel_seq) because the ESC 1 / ESC 2
    grammar does not benefit from a bsearch table.
    * BEEB has no sequence accumulator; VDU 23 (9 trailing bytes) and
    VDU 28 (2 trailing bytes) install the generic
    cterm_accumulate_trailing via cterm->seq_trailing_handler.

    Supporting machinery:

    * Cascade consumption tracking (seq_consumed[] bitmap + seq_consumed_any
    latch) so handlers like SGR/DECSM can split across standards without
    the "empty list -> apply default" path clobbering already-consumed
    parameters.
    * Accumulators for multi-byte state: ecma_seq, prestel_seq,
    command_string, sos, music, font, doorway, trailing (+ ATASCII's
    one-shot atascii_literal_byte installed directly on cterm).
    * Dispatch entries carry a `trailing` count; when set, the matching
    handler is deferred until cterm_accumulate_trailing collects N
    raw bytes into seq_param_int[] (VT52 ESC Y / ESC b / ESC c).
    * Handlers in new files follow a cterm_handle_<name> convention;
    promoted statics uniformly gain the cterm_ prefix. The static
    library exports no unprefixed symbols.

    283/283 cterm_test + 67/67 termtest cases pass.

    Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

    ---
    ■ Synchronet ■ Vertrauen ■ Home of Synchronet ■ [vert/cvs/bbs].synchro.net