BBS:      TELESC.NET.BR
Assunto:  src/syncterm/Wren.adoc src/syncterm/scripts/console.wren syncterm.wren
De:       Deuc¨
Data:     Tue, 28 Apr 2026 04:20:01 -0700
-----------------------------------------------------------
https://gitlab.synchro.net/main/sbbs/-/commit/e2528de46b9d76fdceb6ea0d
Modified Files:
	src/syncterm/Wren.adoc src/syncterm/scripts/console.wren syncterm.wren src/syncterm/term.c wren_bind.c wren_host.c wren_host.h wren_host_internal.h
Log Message:
SyncTERM: Wren API audit + Directory rework + doc completeness pass

Three threads, committed together because they overlap in the same files:

API shape audit
---------------
* Input.next, Input.poll, Input.nextEvent  converted from getters
  to methods (Input.next(), Input.poll(), Input.nextEvent()).  The
  rule "getters are for things that feel like variable access, not
  things that feel like they're doing something"  these block,
  poll, or park a fiber, so they're actions.
* Directory.list  converted from method to a foreign Map getter.
  The directory's contents read like a property; indexing
  `Cache.list["RIP"]` returns the File or Directory handle for that
  name (or null), which composes naturally for tree traversal:
  `Cache.list["RIP"].list["icons.dat"]`.

Directory rework
----------------
* Directory.create(name)  now actually creates the file (was a
  no-op File-object factory).  Uses C11 exclusive-create
  (fopen("wbx")) for race-free atomic creation.  Returns null on
  any failure (file exists, invalid name, path too long, OS reject).
* Directory.createDir(name)  added.  Mirrors create() for
  subdirectories via MKDIR (which is naturally exclusive).
* Directory.delete(name)  added.  Parent-acts-on-child shape:
  removes the named entry (regular file or empty directory only;
  refuses symlinks, devices, FIFOs).  Returns bool.
* File.delete()  removed.  The instance-method-that-zombies-its-
  receiver shape was awkward; Directory.delete(name) covers the
  case from the parent.
* Directory.list now returns Files AND Directories  the C
  implementation always built a Map keyed by name with File values
  for regular files; this extends it to also emit Directory values
  for subdirectories, matching the documented intent.

Live-handle registry
--------------------
A successful Directory.delete shouldn't leave outstanding handles
to the removed entry quietly operating on stale paths.  Each
wren_file and wren_directory now self-registers on a doubly-linked
list rooted on wren_host_state.  Helpers fs_register_*,
fs_unregister_*, fs_kill_*, fs_invalidate_subtree.

Two layers of staleness protection on every File / Directory
operation:

1. dead flag  set by fs_invalidate_subtree when a parent's
   delete removes the entry (or marks an ancestor).  file_check /
   dir_check (called at the top of every method) abort the fiber
   on dead.
2. Per-call fexist() / isdir()  catches deletions that bypassed
   Directory.delete (other process, the user, another script).
   On miss: fs_kill_*(handle) (mark dead + unregister) + throw.

Open-file exemption: a File between open() and close() skips
the fexist() check (its fd is authoritative  Unix lets reads/
writes continue past unlink, and Windows refuses to delete
open files at all).  fs_invalidate_subtree skips fp != NULL
entries on the same logic.  fn_File_close re-runs fexist()
after fclose; if the path is gone, the handle becomes dead.

Wren.adoc completeness pass
---------------------------
Stale "see ciolib.h" references replaced with full reference
content:
* Codepage  every entry described, _b suffix explained.
* Key  full grouped tables (ASCII / cursor / modified Insert-
  Delete / modified arrows / function keys with all four modifier
  columns / synthetic markers).
* Font  full 46-row table including the 1-31 unnamed-in-Wren
  slots that are still reachable numerically; "thin"/"swiss"
  font-style annotations explained.
* Screen.supports, Screen.videoFlags  every flag described.
* ConnType, Emulation, BBSListType, ScreenMode, AddressFamily,
  MusicMode, RipVersion, Parity, FlowControl, LogLevel, ExtAttr,
  LastColumnFlag, LogMode, StatusDisplay  all converted from
  bare name lists to descriptive tables.

Corrections to wrong descriptions:
* sxScroll  SIXEL scroll mode (not "smooth scroll" / DECSCLM).
* blinkAltChars  repurposes attribute bit 7 to select the alt
  character set (not "animate alt-char-set on blink interval").
* StatusDisplay  VT320 DECSSDT semantics (host-writable status
  line, not "verbose status showing connected host").

Worked example replaced.  The "auto-respond to a prompt" example
was using onInput + manual line buffering with a logic bug that
only checked for prompts on LF (so "Logon: "  which has no
trailing LF  never matched).  Replaced with a Hook.onMatch
two-liner; added a smaller per-byte BEL-counter example that
demonstrates onInput correctly without the broken pattern.

Anchors added: [[hook-events]], [[modal-input]], [[codepage]],
[[filename-policy]], [[directory-handle-staleness]] so the
existing <<...>> cross-refs resolve.

Co-Authored-By: Claude Opus 4.7 (1M context) 
n
---
  mSynchronetn  hgVertrauen n hHome of Synchronet n gh[vert/cvs/bbs].synchro.net

-----------------------------------------------------------
[Voltar]