]> git.eshelyaron.com Git - emacs.git/commitdiff
Simplify make_formatted_string API
authorPaul Eggert <eggert@cs.ucla.edu>
Mon, 27 Jan 2025 06:15:48 +0000 (22:15 -0800)
committerEshel Yaron <me@eshelyaron.com>
Thu, 30 Jan 2025 18:06:21 +0000 (19:06 +0100)
From a suggestion by Pip Cet.
* src/alloc.c (make_formatted_string): Omit first argument,
to simplify the calling convention.  All callers changed.
* src/doprnt.c (doprnt): Also support %u.  Update doc.

(cherry picked from commit f885806fdf1aa862ad55d124e9795794fed0b964)

src/alloc.c
src/dbusbind.c
src/doprnt.c
src/frame.c
src/image.c
src/lisp.h
src/msdos.c
src/xsettings.c

index c4e2ff520154dd6d567f5d98efd01f40980ec06c..2c0ccc9dd62868b1079c4ae9ddff9922323b99e1 100644 (file)
@@ -2542,19 +2542,23 @@ make_uninit_multibyte_string (EMACS_INT nchars, EMACS_INT nbytes)
   return make_clear_multibyte_string (nchars, nbytes, false);
 }
 
-/* Print arguments to BUF according to a FORMAT, then return
-   a Lisp_String initialized with the data from BUF.  */
+/* Return a Lisp_String according to a doprnt-style FORMAT and args.  */
 
 Lisp_Object
-make_formatted_string (char *buf, const char *format, ...)
+make_formatted_string (const char *format, ...)
 {
+  char buf[64];
+  char *cstr = buf;
+  ptrdiff_t bufsize = sizeof buf;
   va_list ap;
-  int length;
 
   va_start (ap, format);
-  length = vsprintf (buf, format, ap);
+  ptrdiff_t length = evxprintf (&cstr, &bufsize, buf, -1, format, ap);
   va_end (ap);
-  return make_string (buf, length);
+  Lisp_Object ret = make_string (cstr, length);
+  if (cstr != buf)
+    xfree (cstr);
+  return ret;
 }
 
 /* Pin a unibyte string in place so that it won't move during GC.  */
index b590a40c4a9f8c5f302d117f15d555f80ef90efb..d98009f68b4523907ea80b274026367acfe34d51 100644 (file)
@@ -1970,10 +1970,9 @@ syms_of_dbusbind (void)
   {
 #ifdef DBUS_VERSION
     int major, minor, micro;
-    char s[sizeof ".." + 3 * INT_STRLEN_BOUND (int)];
     dbus_get_version (&major, &minor, &micro);
     Vdbus_runtime_version
-      = make_formatted_string (s, "%d.%d.%d", major, minor, micro);
+      = make_formatted_string ("%d.%d.%d", major, minor, micro);
 #else
     Vdbus_runtime_version = Qnil;
 #endif
index 640349cfec4e857981c1e2915c94d66699e8c989..335223f972a0a9e33a012a35f86c95875888c523 100644 (file)
@@ -23,7 +23,7 @@ along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
    supports the following Emacs-specific features:
 
    . For %c conversions, it produces a string with the multibyte representation
-     of the (`int') argument, suitable for display in an Emacs buffer.
+     of the ('int') argument, suitable for display in an Emacs buffer.
 
    . For %s and %c, when field width is specified (e.g., %25s), it accounts for
      the display width of each character, according to char-width-table.  That
@@ -42,8 +42,8 @@ along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
      overflow ptrdiff_t or size_t, to avoid producing strings longer than what
      Emacs can handle.
 
-   OTOH, this function supports only a small subset of the standard C formatted
-   output facilities.  E.g., %u is not supported, precision is ignored
+   On the other hand, this function supports only a small subset of the
+   standard C formatted output facilities.  E.g., precision is ignored
    in %s and %c conversions, and %lld does not necessarily work and
    code should use something like %"pM"d with intmax_t instead.
    (See below for the detailed documentation of what is supported.)
@@ -57,16 +57,17 @@ along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
    also supports the following %-sequences:
 
    %s means print a string argument.
-   %S is treated as %s, for loose compatibility with `Fformat_message'.
-   %d means print a `signed 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
+   %S is treated as %s, for loose compatibility with 'Fformat_message'.
+   %d means print a 'signed int' argument in decimal.
+   %o means print an 'unsigned int' argument in octal.
+   %u means print an 'unsigned int' argument in decimal.
+   %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, depending on the value;
       this is often (though not always) the shorter of the two notations.
-   %c means print a `signed int' argument as a single character.
+   %c means print a 'signed int' argument as a single character.
    %% means produce a literal % character.
 
    A %-sequence other than %% may contain optional flags, width, precision,
@@ -82,18 +83,18 @@ along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
    The + flag character inserts a + before any positive number, while a space
    inserts a space before any positive number; these flags only affect %d, %o,
    %x, %e, %f, and %g sequences.  The - and 0 flags affect the width specifier,
-   as described below.  For signed numerical arguments only, the ` ' (space)
+   as described below.  For signed numerical arguments only, the ' ' (space)
    flag causes the result to be prefixed with a space character if it does not
    start with a sign (+ or -).
 
-   The l (lower-case letter ell) length modifier is a `long' data type
+   The l (lower-case letter ell) length modifier is a 'long' data type
    modifier: it is supported for %d, %o, and %x conversions of integral
    arguments, must immediately precede the conversion specifier, and means that
-   the respective argument is to be treated as `long int' or `unsigned long
+   the respective argument is to be treated as 'long int' or 'unsigned long
    int'.  Similarly, the value of the pD macro means to use ptrdiff_t,
    the value of the pI macro means to use EMACS_INT or EMACS_UINT, the
    value of the PRIdMAX etc. macros means to use intmax_t or uintmax_t,
-   and the empty length modifier means `int' or `unsigned int'.
+   and the empty length modifier means 'int' or 'unsigned int'.
 
    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
@@ -162,16 +163,15 @@ doprnt_non_null_end (char *buffer, ptrdiff_t bufsize, char const *format,
   return nbytes;
 }
 
-/* Generate output from a format-spec FORMAT,
+/* Format to BUFFER (of positive size BUFSIZE) data formated by FORMAT,
    terminated at either the first NUL or (if FORMAT_END is non-null
    and there are no NUL bytes between FORMAT and FORMAT_END)
-   terminated at position FORMAT_END.
+   terminated at position FORMAT_END.  AP specifies format arguments.
    (*FORMAT_END is not part of the format, but must exist and be readable.)
-   Output goes in BUFFER, which has room for BUFSIZE chars.
-   BUFSIZE must be positive.  If the output does not fit, truncate it
-   to fit and return BUFSIZE - 1; if this truncates a multibyte
-   sequence, store '\0' into the sequence's first byte.
-   Returns the number of bytes stored into BUFFER, excluding
+   If the output does not fit, truncate it to fit and return BUFSIZE - 1;
+   if this truncates a multibyte sequence,
+   store '\0' into the sequence's first byte.
+   Return 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.
@@ -349,6 +349,7 @@ doprnt (char *buffer, ptrdiff_t bufsize, const char *format,
              goto doit;
 
            case 'o':
+           case 'u':
            case 'x':
              switch (length_modifier)
                {
index 3820f102c0e6c873fc26620ba388e513914eb346..f2d47d9bc5144373c8ce664e437c12d51b8bdd64 100644 (file)
@@ -1283,8 +1283,6 @@ static struct frame *
 make_terminal_frame (struct terminal *terminal, Lisp_Object parent,
                     Lisp_Object params)
 {
-  char name[sizeof "F" + INT_STRLEN_BOUND (tty_frame_count)];
-
   if (!terminal->name)
     error ("Terminal is not live, can't create new frames on it");
 
@@ -1364,7 +1362,7 @@ make_terminal_frame (struct terminal *terminal, Lisp_Object parent,
   XSETFRAME (frame, f);
   Vframe_list = Fcons (frame, Vframe_list);
 
-  fset_name (f, make_formatted_string (name, "F%"PRIdMAX, ++tty_frame_count));
+  fset_name (f, make_formatted_string ("F%"PRIdMAX, ++tty_frame_count));
 
   SET_FRAME_VISIBLE (f, true);
 
@@ -3504,14 +3502,12 @@ set_term_frame_name (struct frame *f, Lisp_Object name)
   /* If NAME is nil, set the name to F<num>.  */
   if (NILP (name))
     {
-      char namebuf[sizeof "F" + INT_STRLEN_BOUND (tty_frame_count)];
-
       /* Check for no change needed in this very common case
         before we do any consing.  */
       if (frame_name_fnn_p (SSDATA (f->name), SBYTES (f->name)))
        return;
 
-      name = make_formatted_string (namebuf, "F%"PRIdMAX, ++tty_frame_count);
+      name = make_formatted_string ("F%"PRIdMAX, ++tty_frame_count);
     }
   else
     {
@@ -4938,7 +4934,6 @@ gui_report_frame_params (struct frame *f, Lisp_Object *alistptr)
 {
   Lisp_Object tem;
   uintmax_t w;
-  char buf[INT_BUFSIZE_BOUND (w)];
 
   /* Represent negative positions (off the top or left screen edge)
      in a way that Fmodify_frame_parameters will understand correctly.  */
@@ -4989,7 +4984,7 @@ gui_report_frame_params (struct frame *f, Lisp_Object *alistptr)
      warnings.  */
   w = (uintptr_t) FRAME_NATIVE_WINDOW (f);
   store_in_alist (alistptr, Qwindow_id,
-                 make_formatted_string (buf, "%"PRIuMAX, w));
+                 make_formatted_string ("%"PRIuMAX, w));
 #ifdef HAVE_X_WINDOWS
 #ifdef USE_X_TOOLKIT
   /* Tooltip frame may not have this widget.  */
@@ -4997,7 +4992,7 @@ gui_report_frame_params (struct frame *f, Lisp_Object *alistptr)
 #endif
     w = (uintptr_t) FRAME_OUTER_WINDOW (f);
   store_in_alist (alistptr, Qouter_window_id,
-                 make_formatted_string (buf, "%"PRIuMAX, w));
+                 make_formatted_string ("%"PRIuMAX, w));
 #endif
   store_in_alist (alistptr, Qicon_name, f->icon_name);
   store_in_alist (alistptr, Qvisibility,
index de6955c2a47b06c965da3fe518b8f74d5971ff39..4350c415d9c1b9a87775af558e87824bc4ba7e2b 100644 (file)
@@ -12601,7 +12601,6 @@ static bool
 gs_load (struct frame *f, struct image *img)
 {
   uintmax_t printnum1, printnum2;
-  char buffer[sizeof " " + 2 * INT_STRLEN_BOUND (intmax_t)];
   Lisp_Object window_and_pixmap_id = Qnil, loader, pt_height, pt_width;
   Lisp_Object frame;
   double in_width, in_height;
@@ -12653,13 +12652,13 @@ gs_load (struct frame *f, struct image *img)
   printnum1 = FRAME_X_DRAWABLE (f);
   printnum2 = img->pixmap;
   window_and_pixmap_id
-    = make_formatted_string (buffer, "%"PRIuMAX" %"PRIuMAX,
+    = make_formatted_string ("%"PRIuMAX" %"PRIuMAX,
                             printnum1, printnum2);
 
   printnum1 = FRAME_FOREGROUND_PIXEL (f);
   printnum2 = FRAME_BACKGROUND_PIXEL (f);
   pixel_colors
-    = make_formatted_string (buffer, "%"PRIuMAX" %"PRIuMAX,
+    = make_formatted_string ("%"PRIuMAX" %"PRIuMAX,
                             printnum1, printnum2);
 
   XSETFRAME (frame, f);
index 28fa4c8037e0ebeaa16824d6834c7ebbff34f725..2faad8951338e4921d6cf1a49450deff58e477e1 100644 (file)
@@ -4592,8 +4592,8 @@ extern Lisp_Object make_uninit_bool_vector (EMACS_INT);
 extern Lisp_Object bool_vector_fill (Lisp_Object, Lisp_Object);
 extern AVOID string_overflow (void);
 extern Lisp_Object make_string (const char *, ptrdiff_t);
-extern Lisp_Object make_formatted_string (char *, const char *, ...)
-  ATTRIBUTE_FORMAT_PRINTF (2, 3);
+extern Lisp_Object make_formatted_string (const char *, ...)
+  ATTRIBUTE_FORMAT_PRINTF (1, 2);
 extern Lisp_Object make_unibyte_string (const char *, ptrdiff_t);
 extern ptrdiff_t vectorlike_nbytes (const union vectorlike_header *hdr);
 
index 63a5400bc7dc4e083754a1d3783e7319246e7852..95eb645304046143103c7ae33c0d400a76d92ac1 100644 (file)
@@ -531,7 +531,6 @@ vga_installed (void)
 void
 dos_set_window_size (int *rows, int *cols)
 {
-  char video_name[30];
   union REGS regs;
   Lisp_Object video_mode;
   int video_mode_value, have_vga = 0;
@@ -547,7 +546,7 @@ dos_set_window_size (int *rows, int *cols)
      use that mode.  */
   video_mode
     = Fsymbol_value (Fintern_soft (make_formatted_string
-                                  (video_name, "screen-dimensions-%dx%d",
+                                  ("screen-dimensions-%dx%d",
                                    *rows, *cols), Qnil));
 
   if (FIXNUMP (video_mode)
index 76f9fae62fe67db93c116e2f5db86bc76915d8d5..30b5ed258aecf521ccf217e2f4cbaeea77517d8c 100644 (file)
@@ -927,17 +927,6 @@ apply_xft_settings (Display_Info *dpyinfo,
       static char const format[] =
        "Antialias: %d, Hinting: %d, RGBA: %d, LCDFilter: %d, "
        "Hintstyle: %d, DPI: %f";
-      enum
-      {
-       d_formats = 5,
-       d_growth = INT_BUFSIZE_BOUND (int) - sizeof "%d",
-       lf_formats = 1,
-       max_f_integer_digits = DBL_MAX_10_EXP + 1,
-       f_precision = 6,
-       lf_growth = (sizeof "-." + max_f_integer_digits + f_precision
-                    - sizeof "%f")
-      };
-      char buf[sizeof format + d_formats * d_growth + lf_formats * lf_growth];
 #ifdef HAVE_XFT
       XftDefaultSet (dpyinfo->display, pat);
 #else
@@ -946,7 +935,7 @@ apply_xft_settings (Display_Info *dpyinfo,
       store_config_changed_event (Qfont_render,
                                  XCAR (dpyinfo->name_list_element));
       Vxft_settings
-       = make_formatted_string (buf, format,
+       = make_formatted_string (format,
                                 oldsettings.aa, oldsettings.hinting,
                                 oldsettings.rgba, oldsettings.lcdfilter,
                                 oldsettings.hintstyle, oldsettings.dpi);