Phase-2 constant-notify work banned printf conversions from the catalogue
and from M_() at format call sites. Whole-sentence formats like
"You give %d %s to %s." cannot be localised that way, so Phase 3 needs a
different contract:
* tests/format/check_formats.py accepts M_("…") as a constant format and
still checks the *source* msgid against mux_vsnprintf's conversions.
* tests/nls/check_nls.py no longer bans formats in the pot; it requires
every catalogue msgstr to carry the same conversion sequence (type and
order) as its msgid. mux_vsnprintf has no positional %1$s yet.
Content: mark rob.cpp's remaining player/staff format templates with M_
(tprintf, mux_sprintf, raw_broadcast for give/kill/suspect). Constants
there were already M_ from the earlier rob notify slice. Regenerate pot,
xx, and the .mo without fuzzy entries.
Verified: make test-format, make test-nls.
Replace ~900 typographic \xE2\x80\x.. escapes (curly quotes, en dashes)
and a few \xE2\x80\230 octal workarounds with real UTF-8 in message
strings under mux/modules and mux/src. Leave stringutil and convert
charset mapping tables as explicit byte sequences.
Next notify slice after create/quota: whole-sentence player messages in
rob.cpp (give/kill) and move.cpp (go/home/take/drop). Leave tprintf
formats and HTML/protocol fragments as T(). Regenerate pot and xx
pseudo-locale (~62 msgids catalog-wide).
Completes the sweep the issue called for. mux_atol returns long, which
is 32-bit on LLP64, so every caller silently truncated on Windows. Two
of those were real defects (the truthiness family and cf_size, fixed in
the preceding commits); the rest were latent, waiting for a value large
enough to matter.
Rather than audit 290 sites for whether each can reach 2^31 today, use
the 64-bit parser everywhere and remove the class. A dbref cannot
overflow now, but nothing stops a later caller passing that same site a
timestamp or a byte count.
Pure 1:1 substitution: 285 lines changed, and every removed line
contained mux_atol while every added line contains mux_atoi64. No
control flow, no types, no behaviour beyond the wider parse.
This is a NO-OP on LP64 -- long is already 64-bit on Linux and macOS, so
the generated code there is unchanged. It only widens the parse on
Windows. Narrowing destinations are unaffected either way: `int x =
mux_atoi64(s)` truncates exactly as `int x = mux_atol(s)` did, on both
models.
Left alone: mux_atol itself in mathutil, its declaration, and three
comments that name it. Callers that genuinely want 32-bit semantics can
still ask for them; none appear to.
Verified on Windows: full solution builds clean with no new warnings,
smoke is 1418 passed / 16 failed / 0 crashes / 306 of 306 dispatched --
identical to before the sweep, with the same 16 build-configuration
failures (exp3 module not loaded, hmac/digest behind UNIX_DIGEST).
Spot checks after the change: the boolean family returns 1 for multiples
of 2^32, cf_size round-trips 3000000000 and still reads -1 as unlimited,
and arithmetic, string and list functions are unchanged.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Add a static factory method and LBuf_Adopt macro that takes ownership
of an externally-allocated pool buffer (e.g., from atr_get/atr_pget).
Also add move constructor and move-assignment so adopt() can return
by value, and null-check the destructor for moved-from state.
Pilot conversion: rob.cpp give_money() atr_pget site now uses
LBuf_Adopt, eliminating the manual free_lbuf and covering two
early-return paths that previously required the free to precede them.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace manual alloc_lbuf/free_lbuf pairs with LBuf RAII wrappers
in 12 engine source files: rob, walk, quota, wiz, session, object,
log, match, move, create, flags, boolexp. This eliminates ~40
explicit free_lbuf calls on error paths that are now handled by
destructors, removing leak risk in early-return and multi-exit
functions (boolexp alone had 13 exit-path frees across two
functions). Buffers returned by atr_get/atr_pget or to callers
are left manual since LBuf cannot adopt externally-allocated
buffers.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>