]> git.eshelyaron.com Git - emacs.git/commitdiff
Improve doprnt and its use in verror. (Bug#8545)
authorEli Zaretskii <eliz@gnu.org>
Mon, 25 Apr 2011 08:04:22 +0000 (11:04 +0300)
committerEli Zaretskii <eliz@gnu.org>
Mon, 25 Apr 2011 08:04:22 +0000 (11:04 +0300)
 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
src/doprnt.c
src/eval.c

index 410a3b15ffb447fd5e4913b8279ff7e126dc29a8..cd03d1fa1860a7b86d93a714e4bc0ae64334eafd 100644 (file)
@@ -1,3 +1,14 @@
+2011-04-25  Eli Zaretskii  <eliz@gnu.org>
+
+       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  <tzz@lifelogs.com>
 
        * gnutls.h: Add GNUTLS_STAGE_CALLBACKS enum to denote we're in the
index f124db13221f96a50447438863e5a89d5c8c1059..3ac1d9963a9c6d7bb8e0a437b552ff7efed1ffdd 100644 (file)
@@ -43,10 +43,54 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
    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:
+
+     %<flags><width><precision>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 <config.h>
 #include <stdio.h>
@@ -79,9 +123,8 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
    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;
 }
index c3676720940cd13372bfe812a5f0f16f71ea8395..d1f327021e6a5009224bbc15f110c67a63db9a0f 100644 (file)
@@ -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);