Alejandro Colomar wrote:
> We voted yesterday the proposal n3750 with the name aprintf(), and the
> votes were 10-8-0 (yes-no-abstention).  Most of those 'no' votes (if not
> all) said it was just about the name.  And the only strong reason they
> brought was that they don't believe this is something that
> implementations would find acceptable, not because of the name itself.
> 
> So, if large implementations do add it, that would invalidate those
> arguments.

It feels safe to add it to Gnulib, because — as shown — several other
packages define aprintf() in the same way. In the worst case, WG14 will
pick a different name, and Gnulib will then follow suit.


2026-03-11  Bruno Haible  <[email protected]>

        vaprintf: Add tests.
        * tests/test-vaprintf.c: New file, based on tests/test-xvasprintf.c.
        * modules/vaprintf-tests: New file.

        vaprintf: New module.
        * lib/stdio.in.h (_GL_ATTRIBUTE_DEALLOC_FREE): New macro, copied from
        lib/string.in.h.
        (free, rpl_free): Define as in lib/string.in.h.
        (aprintf, vaprintf): New declarations.
        * lib/vaprintf.c: New file, based on lib/xvasprintf.c.
        * lib/aprintf.c: New file, based on lib/xasprintf.c.
        * m4/stdio_h.m4 (gl_STDIO_H_REQUIRE_DEFAULTS): Initialize
        GNULIB_VAPRINTF. Require gl_STDLIB_H_REQUIRE_DEFAULTS.
        * modules/stdio-h (Depends-on): Add stdlib-h.
        (Makefile.am): Substitute GNULIB_VAPRINTF, GNULIB_FREE_POSIX,
        REPLACE_FREE.
        * modules/vaprintf: New file.

>From 68143964a370b3a565d081d4d994aee772eaca00 Mon Sep 17 00:00:00 2001
From: Bruno Haible <[email protected]>
Date: Wed, 11 Mar 2026 18:22:19 +0100
Subject: [PATCH 1/2] vaprintf: New module.

* lib/stdio.in.h (_GL_ATTRIBUTE_DEALLOC_FREE): New macro, copied from
lib/string.in.h.
(free, rpl_free): Define as in lib/string.in.h.
(aprintf, vaprintf): New declarations.
* lib/vaprintf.c: New file, based on lib/xvasprintf.c.
* lib/aprintf.c: New file, based on lib/xasprintf.c.
* m4/stdio_h.m4 (gl_STDIO_H_REQUIRE_DEFAULTS): Initialize
GNULIB_VAPRINTF. Require gl_STDLIB_H_REQUIRE_DEFAULTS.
* modules/stdio-h (Depends-on): Add stdlib-h.
(Makefile.am): Substitute GNULIB_VAPRINTF, GNULIB_FREE_POSIX,
REPLACE_FREE.
* modules/vaprintf: New file.
---
 ChangeLog        |  16 ++++++++
 lib/aprintf.c    |  32 +++++++++++++++
 lib/stdio.in.h   |  78 ++++++++++++++++++++++++++++++++++++
 lib/vaprintf.c   | 101 +++++++++++++++++++++++++++++++++++++++++++++++
 m4/stdio_h.m4    |   5 ++-
 modules/stdio-h  |   4 ++
 modules/vaprintf |  31 +++++++++++++++
 7 files changed, 266 insertions(+), 1 deletion(-)
 create mode 100644 lib/aprintf.c
 create mode 100644 lib/vaprintf.c
 create mode 100644 modules/vaprintf

diff --git a/ChangeLog b/ChangeLog
index 6dd220d9f7..a597434c63 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+2026-03-11  Bruno Haible  <[email protected]>
+
+	vaprintf: New module.
+	* lib/stdio.in.h (_GL_ATTRIBUTE_DEALLOC_FREE): New macro, copied from
+	lib/string.in.h.
+	(free, rpl_free): Define as in lib/string.in.h.
+	(aprintf, vaprintf): New declarations.
+	* lib/vaprintf.c: New file, based on lib/xvasprintf.c.
+	* lib/aprintf.c: New file, based on lib/xasprintf.c.
+	* m4/stdio_h.m4 (gl_STDIO_H_REQUIRE_DEFAULTS): Initialize
+	GNULIB_VAPRINTF. Require gl_STDLIB_H_REQUIRE_DEFAULTS.
+	* modules/stdio-h (Depends-on): Add stdlib-h.
+	(Makefile.am): Substitute GNULIB_VAPRINTF, GNULIB_FREE_POSIX,
+	REPLACE_FREE.
+	* modules/vaprintf: New file.
+
 2026-03-11  Bruno Haible  <[email protected]>
 
 	xvasprintf-tests: Fix typo.
diff --git a/lib/aprintf.c b/lib/aprintf.c
new file mode 100644
index 0000000000..aad64eaf6e
--- /dev/null
+++ b/lib/aprintf.c
@@ -0,0 +1,32 @@
+/* Simplified variant of vasprintf and asprintf.
+   Copyright (C) 1999, 2002-2004, 2006, 2009-2026 Free Software Foundation,
+   Inc.
+
+   This file is free software: you can redistribute it and/or modify
+   it under the terms of the GNU Lesser General Public License as
+   published by the Free Software Foundation; either version 2.1 of the
+   License, or (at your option) any later version.
+
+   This file is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public License
+   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include <stdio.h>
+
+char *
+aprintf (const char *format, ...)
+{
+  va_list args;
+  va_start (args, format);
+  char *result = vaprintf (format, args);
+  va_end (args);
+
+  return result;
+}
diff --git a/lib/stdio.in.h b/lib/stdio.in.h
index 33b0b8e48a..4028bfa4fa 100644
--- a/lib/stdio.in.h
+++ b/lib/stdio.in.h
@@ -122,6 +122,20 @@
 # endif
 #endif
 
+/* _GL_ATTRIBUTE_DEALLOC_FREE declares that the function returns pointers that
+   can be freed via 'free'; it can be used only after declaring 'free'.  */
+/* Applies to: functions.  Cannot be used on inline functions.  */
+#ifndef _GL_ATTRIBUTE_DEALLOC_FREE
+# if defined __cplusplus && defined __GNUC__ && !defined __clang__
+/* Work around GCC bug <https://gcc.gnu.org/PR108231> */
+#  define _GL_ATTRIBUTE_DEALLOC_FREE \
+     _GL_ATTRIBUTE_DEALLOC ((void (*) (void *)) free, 1)
+# else
+#  define _GL_ATTRIBUTE_DEALLOC_FREE \
+     _GL_ATTRIBUTE_DEALLOC (free, 1)
+# endif
+#endif
+
 /* The __attribute__ feature is available in gcc versions 2.5 and later.
    The __-protected variants of the attributes 'format' and 'printf' are
    accepted by gcc versions 2.6.4 (effectively 2.7) and later.
@@ -231,6 +245,50 @@
 
 /* The definition of _GL_WARN_ON_USE is copied here.  */
 
+/* Make _GL_ATTRIBUTE_DEALLOC_FREE work, even though <stdlib.h> may not have
+   been included yet.  */
+#if @GNULIB_FREE_POSIX@
+# if (@REPLACE_FREE@ && !defined free \
+      && !(defined __cplusplus && defined GNULIB_NAMESPACE))
+/* We can't do '#define free rpl_free' here.  */
+#  if defined __cplusplus && (__GLIBC__ + (__GLIBC_MINOR__ >= 14) > 2)
+_GL_EXTERN_C void rpl_free (void *) _GL_ATTRIBUTE_NOTHROW;
+#  else
+_GL_EXTERN_C void rpl_free (void *);
+#  endif
+#  undef _GL_ATTRIBUTE_DEALLOC_FREE
+#  define _GL_ATTRIBUTE_DEALLOC_FREE _GL_ATTRIBUTE_DEALLOC (rpl_free, 1)
+# else
+#  if defined _MSC_VER && !defined free
+_GL_EXTERN_C
+#   if defined _DLL
+     __declspec (dllimport)
+#   endif
+     void __cdecl free (void *);
+#  else
+#   if defined __cplusplus && (__GLIBC__ + (__GLIBC_MINOR__ >= 14) > 2)
+_GL_EXTERN_C void free (void *) _GL_ATTRIBUTE_NOTHROW;
+#   else
+_GL_EXTERN_C void free (void *);
+#   endif
+#  endif
+# endif
+#else
+# if defined _MSC_VER && !defined free
+_GL_EXTERN_C
+#   if defined _DLL
+     __declspec (dllimport)
+#   endif
+     void __cdecl free (void *);
+# else
+#  if defined __cplusplus && (__GLIBC__ + (__GLIBC_MINOR__ >= 14) > 2)
+_GL_EXTERN_C void free (void *) _GL_ATTRIBUTE_NOTHROW;
+#  else
+_GL_EXTERN_C void free (void *);
+#  endif
+# endif
+#endif
+
 /* Macros for stringification.  */
 #define _GL_STDIO_STRINGIZE(token) #token
 #define _GL_STDIO_MACROEXPAND_AND_STRINGIZE(token) _GL_STDIO_STRINGIZE(token)
@@ -1808,6 +1866,26 @@ _GL_CXXALIAS_SYS (vasprintf, int,
 _GL_CXXALIASWARN (vasprintf);
 #endif
 
+#if @GNULIB_VAPRINTF@
+/* Write formatted output to a string dynamically allocated with malloc().
+   Return the resulting string.  Upon memory allocation error, or some
+   other error, return NULL, with errno set.  */
+_GL_FUNCDECL_SYS (aprintf, char *,
+                  (const char *format, ...),
+                  _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (1, 2)
+                  _GL_ARG_NONNULL ((1))
+                  _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE);
+_GL_CXXALIAS_SYS (aprintf, char *,
+                  (const char *format, ...));
+_GL_FUNCDECL_SYS (vaprintf, char *,
+                  (const char *format, va_list args),
+                  _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (1, 0)
+                  _GL_ARG_NONNULL ((1))
+                  _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE);
+_GL_CXXALIAS_SYS (vaprintf, char *,
+                  (const char *format, va_list args));
+#endif
+
 #if @GNULIB_VDZPRINTF@
 /* Prints formatted output to file descriptor FD.
    Returns the number of bytes written to the file descriptor.  Upon
diff --git a/lib/vaprintf.c b/lib/vaprintf.c
new file mode 100644
index 0000000000..58147e1ce1
--- /dev/null
+++ b/lib/vaprintf.c
@@ -0,0 +1,101 @@
+/* Simplified variant of vasprintf and asprintf.
+   Copyright (C) 1999, 2002-2004, 2006-2026 Free Software Foundation, Inc.
+
+   This file is free software: you can redistribute it and/or modify
+   it under the terms of the GNU Lesser General Public License as
+   published by the Free Software Foundation; either version 2.1 of the
+   License, or (at your option) any later version.
+
+   This file is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public License
+   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include <stdio.h>
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* Checked size_t computations.  */
+#include "xsize.h"
+
+static char *
+astrcat (size_t argcount, va_list args)
+{
+  /* Determine the total size.  */
+  size_t totalsize = 0;
+  {
+    va_list ap;
+    va_copy (ap, args);
+    for (size_t i = argcount; i > 0; i--)
+      {
+        const char *next = va_arg (ap, const char *);
+        totalsize = xsum (totalsize, strlen (next));
+      }
+    va_end (ap);
+  }
+
+  /* Test for overflow in the summing pass above or in (totalsize + 1)
+     below.  */
+  if (totalsize == SIZE_MAX)
+    {
+      errno = ENOMEM;
+      return NULL;
+    }
+
+  /* Allocate and fill the result string.  */
+  char *result = (char *) malloc (totalsize + 1);
+  if (result == NULL)
+    return NULL;
+  {
+    char *p = result;
+    for (size_t i = argcount; i > 0; i--)
+      {
+        const char *next = va_arg (args, const char *);
+        size_t len = strlen (next);
+        memcpy (p, next, len);
+        p += len;
+      }
+    *p = '\0';
+  }
+
+  return result;
+}
+
+char *
+vaprintf (const char *format, va_list args)
+{
+  /* Recognize the special case format = "%s...%s".  It is a frequently used
+     idiom for string concatenation and needs to be fast.  We don't want to
+     have a separate function astrcat() for this purpose.  */
+  {
+    size_t argcount = 0;
+
+    for (const char *f = format;;)
+      {
+        if (*f == '\0')
+          /* Recognized the special case of string concatenation.  */
+          return astrcat (argcount, args);
+        if (*f != '%')
+          break;
+        f++;
+        if (*f != 's')
+          break;
+        f++;
+        argcount++;
+      }
+  }
+
+  char *result;
+  if (vaszprintf (&result, format, args) < 0)
+    return NULL;
+
+  return result;
+}
diff --git a/m4/stdio_h.m4 b/m4/stdio_h.m4
index 9d4126f586..0be1fd98ea 100644
--- a/m4/stdio_h.m4
+++ b/m4/stdio_h.m4
@@ -1,5 +1,5 @@
 # stdio_h.m4
-# serial 75
+# serial 76
 dnl Copyright (C) 2007-2026 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -182,6 +182,7 @@ AC_DEFUN([gl_STDIO_H_REQUIRE_DEFAULTS]
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_STDIO_H_SIGPIPE])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_SZPRINTF])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_TMPFILE])
+    gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_VAPRINTF])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_VASPRINTF])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_VASZPRINTF])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_VFSCANF])
@@ -208,6 +209,8 @@ AC_DEFUN([gl_STDIO_H_REQUIRE_DEFAULTS]
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_MDA_TEMPNAM], [1])
   ])
   m4_require(GL_MODULE_INDICATOR_PREFIX[_STDIO_H_MODULE_INDICATOR_DEFAULTS])
+  dnl Make sure the shell variable for GNULIB_FREE_POSIX is initialized.
+  gl_STDLIB_H_REQUIRE_DEFAULTS
   AC_REQUIRE([gl_STDIO_H_DEFAULTS])
 ])
 
diff --git a/modules/stdio-h b/modules/stdio-h
index 51940a8a8d..cc2f8f2a50 100644
--- a/modules/stdio-h
+++ b/modules/stdio-h
@@ -17,6 +17,7 @@ snippet/c++defs
 snippet/warn-on-use
 ssize_t
 stddef-h
+stdlib-h
 sys_types-h
 stdio-windows
 
@@ -117,6 +118,7 @@ stdio.h: stdio.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H)
 	      -e 's/@''GNULIB_STDIO_H_SIGPIPE''@/$(GNULIB_STDIO_H_SIGPIPE)/g' \
 	      -e 's/@''GNULIB_SZPRINTF''@/$(GNULIB_SZPRINTF)/g' \
 	      -e 's/@''GNULIB_TMPFILE''@/$(GNULIB_TMPFILE)/g' \
+	      -e 's/@''GNULIB_VAPRINTF''@/$(GNULIB_VAPRINTF)/g' \
 	      -e 's/@''GNULIB_VASPRINTF''@/$(GNULIB_VASPRINTF)/g' \
 	      -e 's/@''GNULIB_VASZPRINTF''@/$(GNULIB_VASZPRINTF)/g' \
 	      -e 's/@''GNULIB_VDPRINTF''@/$(GNULIB_VDPRINTF)/g' \
@@ -140,6 +142,7 @@ stdio.h: stdio.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H)
 	      -e 's/@''GNULIB_MDA_GETW''@/$(GNULIB_MDA_GETW)/g' \
 	      -e 's/@''GNULIB_MDA_PUTW''@/$(GNULIB_MDA_PUTW)/g' \
 	      -e 's/@''GNULIB_MDA_TEMPNAM''@/$(GNULIB_MDA_TEMPNAM)/g' \
+	      -e 's/@''GNULIB_FREE_POSIX''@/$(GNULIB_FREE_POSIX)/g' \
 	      < $(srcdir)/stdio.in.h > $@-t1
 	$(AM_V_at)sed \
 	      -e 's|@''HAVE_DECL_FCLOSEALL''@|$(HAVE_DECL_FCLOSEALL)|g' \
@@ -171,6 +174,7 @@ stdio.h: stdio.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H)
 	      -e 's|@''REPLACE_FOPEN_FOR_FOPEN_GNU''@|$(REPLACE_FOPEN_FOR_FOPEN_GNU)|g' \
 	      -e 's|@''REPLACE_FPRINTF''@|$(REPLACE_FPRINTF)|g' \
 	      -e 's|@''REPLACE_FPURGE''@|$(REPLACE_FPURGE)|g' \
+	      -e 's|@''REPLACE_FREE''@|$(REPLACE_FREE)|g' \
 	      -e 's|@''REPLACE_FREOPEN''@|$(REPLACE_FREOPEN)|g' \
 	      -e 's|@''REPLACE_FSEEK''@|$(REPLACE_FSEEK)|g' \
 	      -e 's|@''REPLACE_FSEEKO''@|$(REPLACE_FSEEKO)|g' \
diff --git a/modules/vaprintf b/modules/vaprintf
new file mode 100644
index 0000000000..0ec945c95d
--- /dev/null
+++ b/modules/vaprintf
@@ -0,0 +1,31 @@
+Description:
+Simplified variant of vasprintf and asprintf.
+
+Files:
+lib/vaprintf.c
+lib/aprintf.c
+
+Depends-on:
+stdio-h
+vaszprintf
+malloc-posix
+xsize
+stdarg-h
+errno-h
+
+configure.ac:
+gl_STDIO_MODULE_INDICATOR([vaprintf])
+m4_ifdef([AM_XGETTEXT_OPTION],
+  [AM_][XGETTEXT_OPTION([--flag=aprintf:1:c-format])])
+
+Makefile.am:
+lib_SOURCES += vaprintf.c aprintf.c
+
+Include:
+<stdio.h>
+
+License:
+LGPLv2+
+
+Maintainer:
+all
-- 
2.52.0

>From 471bf820b4844721fd7176165717d49eead0b8a2 Mon Sep 17 00:00:00 2001
From: Bruno Haible <[email protected]>
Date: Wed, 11 Mar 2026 18:23:43 +0100
Subject: [PATCH 2/2] vaprintf: Add tests.

* tests/test-vaprintf.c: New file, based on tests/test-xvasprintf.c.
* modules/vaprintf-tests: New file.
---
 ChangeLog              |   4 ++
 modules/vaprintf-tests |  13 ++++
 tests/test-vaprintf.c  | 133 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 150 insertions(+)
 create mode 100644 modules/vaprintf-tests
 create mode 100644 tests/test-vaprintf.c

diff --git a/ChangeLog b/ChangeLog
index a597434c63..71d77dc037 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,9 @@
 2026-03-11  Bruno Haible  <[email protected]>
 
+	vaprintf: Add tests.
+	* tests/test-vaprintf.c: New file, based on tests/test-xvasprintf.c.
+	* modules/vaprintf-tests: New file.
+
 	vaprintf: New module.
 	* lib/stdio.in.h (_GL_ATTRIBUTE_DEALLOC_FREE): New macro, copied from
 	lib/string.in.h.
diff --git a/modules/vaprintf-tests b/modules/vaprintf-tests
new file mode 100644
index 0000000000..1405b56b12
--- /dev/null
+++ b/modules/vaprintf-tests
@@ -0,0 +1,13 @@
+Files:
+tests/test-vaprintf.c
+tests/macros.h
+
+Depends-on:
+streq
+
+configure.ac:
+
+Makefile.am:
+TESTS += test-vaprintf
+check_PROGRAMS += test-vaprintf
+
diff --git a/tests/test-vaprintf.c b/tests/test-vaprintf.c
new file mode 100644
index 0000000000..21f0c6e1d5
--- /dev/null
+++ b/tests/test-vaprintf.c
@@ -0,0 +1,133 @@
+/* Test of vaprintf() and aprintf() functions.
+   Copyright (C) 2007-2026 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
+
+/* Written by Bruno Haible <[email protected]>, 2026.  */
+
+#include <config.h>
+
+/* Tell GCC not to warn about the specific edge cases tested here.  */
+#if _GL_GNUC_PREREQ (4, 3)
+# pragma GCC diagnostic ignored "-Wformat-zero-length"
+# pragma GCC diagnostic ignored "-Wformat-nonliteral"
+# pragma GCC diagnostic ignored "-Wformat-security"
+#endif
+
+#include <stdio.h>
+
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "macros.h"
+
+static char *
+my_aprintf (const char *format, ...)
+{
+  va_list args;
+  char *ret;
+
+  va_start (args, format);
+  ret = vaprintf (format, args);
+  va_end (args);
+  return ret;
+}
+
+static void
+test_vaprintf (void)
+{
+  char *result;
+
+  for (int repeat = 0; repeat <= 8; repeat++)
+    {
+      result = my_aprintf ("%d", 12345);
+      ASSERT (result != NULL);
+      ASSERT (streq (result, "12345"));
+      free (result);
+    }
+
+  {
+    /* Silence gcc warning about zero-length format string.  */
+    const char *empty = "";
+    result = my_aprintf (empty);
+    ASSERT (result != NULL);
+    ASSERT (streq (result, ""));
+    free (result);
+  }
+
+  result = my_aprintf ("%s", "foo");
+  ASSERT (result != NULL);
+  ASSERT (streq (result, "foo"));
+  free (result);
+
+  result = my_aprintf ("%s%s", "foo", "bar");
+  ASSERT (result != NULL);
+  ASSERT (streq (result, "foobar"));
+  free (result);
+
+  result = my_aprintf ("%s%sbaz", "foo", "bar");
+  ASSERT (result != NULL);
+  ASSERT (streq (result, "foobarbaz"));
+  free (result);
+}
+
+static void
+test_aprintf (void)
+{
+  char *result;
+
+  for (int repeat = 0; repeat <= 8; repeat++)
+    {
+      result = aprintf ("%d", 12345);
+      ASSERT (result != NULL);
+      ASSERT (streq (result, "12345"));
+      free (result);
+    }
+
+  {
+    /* Silence gcc warning about zero-length format string,
+       and about "format not a string literal and no format"
+       (whatever that means) .  */
+    const char *empty = "";
+    result = aprintf (empty, empty);
+    ASSERT (result != NULL);
+    ASSERT (streq (result, ""));
+    free (result);
+  }
+
+  result = aprintf ("%s", "foo");
+  ASSERT (result != NULL);
+  ASSERT (streq (result, "foo"));
+  free (result);
+
+  result = aprintf ("%s%s", "foo", "bar");
+  ASSERT (result != NULL);
+  ASSERT (streq (result, "foobar"));
+  free (result);
+
+  result = aprintf ("%s%sbaz", "foo", "bar");
+  ASSERT (result != NULL);
+  ASSERT (streq (result, "foobarbaz"));
+  free (result);
+}
+
+int
+main (_GL_UNUSED int argc, char *argv[])
+{
+  test_vaprintf ();
+  test_aprintf ();
+
+  return test_exit_status;
+}
-- 
2.52.0

Reply via email to