[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
bug#43439: [PATCH] doprnt improvements
From: |
Paul Eggert |
Subject: |
bug#43439: [PATCH] doprnt improvements |
Date: |
Wed, 16 Sep 2020 15:09:50 -0700 |
User-agent: |
Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.10.0 |
On 9/16/20 7:58 AM, Eli Zaretskii wrote:
Emacs traditionally supports strings with
embedded null characters, and this feature is in line with that. It
is true that it is currently unused, but why is it a good idea to
remove it?
It's a good idea not only because the feature is currently unused and its
support complicates and adds bugs to the code, but also because it would be a
bad idea to ever use the feature.
The Emacs feature is for Lisp strings. Emacs does not (and for API reasons, it
cannot practically) rely on embedded NULs in C strings. Among other things, if
we tried to use C-style printf formats with embedded NULs, GCC's warnings about
formats not matching their arguments would stop working. These GCC warnings are
quite useful for preventing bugs in Emacs's C code and have helped to catch many
such bugs, and we should not give them up.
More generally, the vestigial support for NULs and %S in doprnt's C formats
dates back to long ago, before GCC warned about these features. It may have made
sense back then but it does not make sense now. Any C-level formatting facility
that supports NULs and %S should not attempt to use the longstanding printf API
that is incompatible with such support - it should be a separate facility. And
Emacs C code already has a non-printf facility for formatting with NULs and %S -
e.g., Fformat and Fformat_message - so it doesn't need yet another one.
If the problem is the slight inefficiency caused by the call to
strlen, we could instead solve it in the callers: all the formats I've
seen are const strings, so the value of FORMAT_END can be computed at
compile time, and used instead of passing NULL.
This would require unnecessary complication of the code and runtime overhead.
doprnt is called directly only in few places: esprintf, evxprintf, vmessage, and
the (rarely-if-ever used) snprintf replacement. If we modified callers to do
what you're suggesting, we'd need to modify the callers of these functions, and
their callers too, all the way back to the original ancestor call that specifies
the format. This would clutter and bloat the code and would add runtime cost to
all the callers. For example, we'd have to change all calls to the 'error'
function from something like this:
if (ret < GNUTLS_E_SUCCESS)
error ("GnuTLS AEAD cipher %s/%s initialization failed: %s",
gnutls_cipher_get_name (gca), desc, emacs_gnutls_strerror (ret));
to something like this:
if (ret < GNUTLS_E_SUCCESS)
{
char const msg[] = "GnuTLS AEAD cipher %s/%s initialization failed: %s";
error (msg, sizeof msg - 1,
gnutls_cipher_get_name (gca), desc, emacs_gnutls_strerror (ret));
}
Of course we could invent a new macro ERROR to package this up, but such a macro
would still be less efficient than what we have, and worse it would not always
work, for cases like this:
if (NILP (tem) || (XBUFFER (tem) != current_buffer))
error (for_region ? "The mark is not set now, so there is no region"
: "The mark is not set now");
or like this:
error (format, string); // in x_check_errors
And of course this could be gotten around as well, but we're now talking about a
reasonably large amount of code surgery that will hurt code readability and
runtime performance, all to support a low-level C feature that Emacs does not
use and won't ever reasonably use.
Instead, we should leave most of the C code alone and just adjust 'doprnt' and
its very few callers.
Drop support for
"%S" which is never used and which would cause GCC to warn anyway.
This is an old compatibility feature, I'd rather not drop it. Who
knows what code relies on the fact that 'message' and 'format-message'
support it?
I know because I checked all the code. No Emacs C code uses %S. And none is
likely to use it in the future because GCC warns about it if you try. (To be
specific: GCC warns unless you use %S compatibly with its standard C meaning,
which differs from that of Emacs doprnt - which is yet another compatibility
minefield if we insist on keeping doprnt's unused %S feature.)