From 825cd63ca98121d602b4a8dcffa55d29841224a0 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Mon, 25 Apr 2011 11:04:22 +0300 Subject: [PATCH] Improve doprnt and its use in verror. (Bug#8545) src/doprnt.c (doprnt): Document the set of format control sequences supported by the function. Use SAFE_ALLOCA instead of always using `alloca'. src/eval.c (verror): Don't limit the buffer size at size_max-1, that is one byte too soon. Don't use xrealloc; instead xfree and xmalloc anew. --- src/ChangeLog | 11 +++++++++ src/doprnt.c | 62 ++++++++++++++++++++++++++++++++++++++++++++------- src/eval.c | 11 +++++---- 3 files changed, 70 insertions(+), 14 deletions(-) diff --git a/src/ChangeLog b/src/ChangeLog index 410a3b15ffb..cd03d1fa186 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,14 @@ +2011-04-25 Eli Zaretskii + + Improve doprnt and its use in verror. (Bug#8545) + * doprnt.c (doprnt): Document the set of format control sequences + supported by the function. Use SAFE_ALLOCA instead of always + using `alloca'. + + * eval.c (verror): Don't limit the buffer size at size_max-1, that + is one byte too soon. Don't use xrealloc; instead xfree and + xmalloc anew. + 2011-04-24 Teodor Zlatanov * gnutls.h: Add GNUTLS_STAGE_CALLBACKS enum to denote we're in the diff --git a/src/doprnt.c b/src/doprnt.c index f124db13221..3ac1d9963a9 100644 --- a/src/doprnt.c +++ b/src/doprnt.c @@ -43,10 +43,54 @@ along with GNU Emacs. If not, see . */ OTOH, this function supports only a small subset of the standard C formatted output facilities. E.g., %u and %ll are not supported, and precision is - largely ignored except for converting floating-point values. However, this - is okay, as this function is supposed to be called from `error' and similar - functions, and thus does not need to support features beyond those in - `Fformat', which is used by `error' on the Lisp level. */ + ignored %s and %c conversions. (See below for the detailed documentation of + what is supported.) However, this is okay, as this function is supposed to + be called from `error' and similar functions, and thus does not need to + support features beyond those in `Fformat', which is used by `error' on the + Lisp level. */ + +/* This function supports the following %-sequences in the `format' + argument: + + %s means print a string argument. + %S is silently treated as %s, for loose compatibility with `Fformat'. + %d means print a `signed int' argument in decimal. + %l means print a `long int' argument in decimal. + %o means print an `unsigned int' argument in octal. + %x means print an `unsigned int' argument in hex. + %e means print a `double' argument in exponential notation. + %f means print a `double' argument in decimal-point notation. + %g means print a `double' argument in exponential notation + or in decimal-point notation, whichever uses fewer characters. + %c means print a `signed int' argument as a single character. + %% means produce a literal % character. + + A %-sequence may contain optional flag, width, and precision specifiers, as + follows: + + %character + + where flags is [+ -0l], width is [0-9]+, and precision is .[0-9]+ + + The + flag character inserts a + before any positive number, while a space + inserts a space before any positive number; these flags only affect %d, %l, + %o, %x, %e, %f, and %g sequences. The - and 0 flags affect the width + specifier, as described below. + + The l (lower-case letter ell) flag is a `long' data type modifier: it is + supported for %d, %o, and %x conversions of integral arguments, and means + that the respective argument is to be treated as `long int' or `unsigned + long int'. The EMACS_INT data type should use this modifier. + + The width specifier supplies a lower limit for the length of the printed + representation. The padding, if any, normally goes on the left, but it goes + on the right if the - flag is present. The padding character is normally a + space, but (for numerical arguments only) it is 0 if the 0 flag is present. + The - flag takes precedence over the 0 flag. + + For %e, %f, and %g sequences, the number after the "." in the precision + specifier says how many decimal places to show; if zero, the decimal point + itself is omitted. For %s and %S, the precision specifier is ignored. */ #include #include @@ -79,9 +123,8 @@ along with GNU Emacs. If not, see . */ terminated at position FORMAT_END. Output goes in BUFFER, which has room for BUFSIZE chars. If the output does not fit, truncate it to fit. - Returns the number of bytes stored into BUFFER. - ARGS points to the vector of arguments, and NARGS says how many. - A double counts as two arguments. + Returns the number of bytes stored into BUFFER, excluding + the terminating null byte. Output is always null-terminated. String arguments are passed as C strings. Integers are passed as C integers. */ @@ -110,6 +153,7 @@ doprnt (char *buffer, register size_t bufsize, const char *format, char *fmtcpy; int minlen; char charbuf[MAX_MULTIBYTE_LENGTH + 1]; /* Used for %c. */ + USE_SAFE_ALLOCA; if (format_end == 0) format_end = format + strlen (format); @@ -117,7 +161,7 @@ doprnt (char *buffer, register size_t bufsize, const char *format, if ((format_end - format + 1) < sizeof (fixed_buffer)) fmtcpy = fixed_buffer; else - fmtcpy = (char *) alloca (format_end - format + 1); + SAFE_ALLOCA (fmtcpy, char *, format_end - format + 1); bufsize--; @@ -342,5 +386,7 @@ doprnt (char *buffer, register size_t bufsize, const char *format, xfree (big_buffer); *bufptr = 0; /* Make sure our string ends with a '\0' */ + + SAFE_FREE (); return bufptr - buffer; } diff --git a/src/eval.c b/src/eval.c index c3676720940..d1f327021e6 100644 --- a/src/eval.c +++ b/src/eval.c @@ -2012,15 +2012,14 @@ verror (const char *m, va_list ap) break; if (size <= size_max / 2) size *= 2; - else if (size < size_max - 1) - size = size_max - 1; + else if (size < size_max) + size = size_max; else break; /* and leave the message truncated */ - if (buffer == buf) - buffer = (char *) xmalloc (size); - else - buffer = (char *) xrealloc (buffer, size); + if (buffer != buf) + xfree (buffer); + buffer = (char *) xmalloc (size); } string = make_string (buffer, used); -- 2.39.2